1 动规-打家劫舍一
你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家,就不能再偷第二家;如果偷了第二家,那么就不能偷第一家和第三家。给定一个整数数组nums,数组中的元素表示每个房间存有的现金数额,请你计算在不被发现的前提下最多的偷窃金额。
import java.util.*;
public class Solution {
public int rob (int[] nums) {
//dp[i]表示长度为i的数组,最多能偷取多少钱
int[] dp = new int[nums.length + 1];
//长度为1只能偷第一家
dp[1] = nums[0];
for(int i = 2; i <= nums.length; i++)
//对于每家可以选择偷或者不偷
dp[i] = Math.max(dp[i - 1], nums[i - 1] + dp[i - 2]);
return dp[nums.length];
}
}
2 动规-打家劫舍二
你是一个经验丰富的小偷,准备偷沿湖的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家,就不能再偷第二家,如果偷了第二家,那么就不能偷第一家和第三家。沿湖的房间组成一个闭合的圆形,即第一个房间和最后一个房间视为相邻。
给定一个长度为n的整数数组nums,数组中的元素表示每个房间存有的现金数额,请你计算在不被发现的前提下最多的偷窃金额。
import java.util.*;
public class Solution {
public int rob (int[] nums) {
//dp[i]表示长度为i的数组,最多能偷取多少钱
int[] dp = new int[nums.length + 1];
//选择偷了第一家
dp[1] = nums[0];
//最后一家不能偷
for(int i = 2; i < nums.length; i++)
//对于每家可以选择偷或者不偷
dp[i] = Math.max(dp[i - 1], nums[i - 1] + dp[i - 2]);
int res = dp[nums.length - 1];
//清除dp数组,第二次循环
Arrays.fill(dp, 0);
//不偷第一家
dp[1] = 0;
//可以偷最后一家
for(int i = 2; i <= nums.length; i++)
//对于每家可以选择偷或者不偷
dp[i] = Math.max(dp[i - 1], nums[i - 1] + dp[i - 2]);
//选择最大值
return Math.max(res, dp[nums.length]);
}
}
import java.util.*;
public class Solution {
public int rob (int[] nums) {
int n=nums.length;
//在0到n-2范围内找
int rob1=getRob(nums,0,n-1);
//在1到n-1范围内找
int rob2=getRob(nums,1,n);
return Math.max(rob1,rob2);
}
private int getRob(int[] nums,int start,int end){
//记录到前前家为止最多偷多少
int prepre=0;
//记录到前一家为止最多偷多少
int pre=0;
int n=nums.length;
for(int i=start;i<end;i++){
//要么是前前家+当前,要么是前一家,取较大者
int cur=Math.max(prepre+nums[i],pre);
//状态后移
prepre=pre;
pre=cur;
}
return pre;
}
}
3 动规-背包问题一
你有一个背包,最多能容纳的体积是V。现在有n个物品,第i个物品的体积为Vi,价值为wi
(1)求这个背包至多能装多大价值的物品?
(2)若背包恰好装满,求至多能装多大价值的物品?
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int V = sc.nextInt();
//存放体积
int[] v=new int[n+1];
//存放价值
int[] w=new int[n+1];
for(int i=1;i<=n;i++){
v[i]=sc.nextInt();
w[i]=sc.nextInt();
}
//dp1[i]表示不考虑背包是否装满,在容量为i的情况下,最多装多大价值的物品
int[] dp1=new int[V+1];
for(int i=1;i<=n;i++){
//由于每个物品只能用一次,为了防止重复计算,需要倒序遍历
for(int j=V;j>=v[i];j--){
//状态转移,要么选择第i件物品,要么不选,取价值最大的
dp1[j]=Math.max(dp1[j-v[i]]+w[i],dp1[j]);
}
}
System.out.println(dp1[V]);
//dp2[i]表示背包恰好装满时,在容量为i的情况下,最多装多大价值的物品
int[] dp2=new int[V+1];
Arrays.fill(dp2,Integer.MIN_VALUE);
//没有物品时,价值为0
dp2[0]=0;
for(int i=1;i<=n;i++){
//由于每个物品只能用一次,为了防止重复计算,需要倒序遍历
for(int j=V;j>=v[i];j--){
//状态转移,要么选择第i件物品,要么不选,取价值最大的
dp2[j]=Math.max(dp2[j-v[i]]+w[i],dp2[j]);
}
}
//如果小于0,说明不能从初始状态转移过来,无解
if(dp2[V]<0){
dp2[V]=0;
}
System.out.println(dp2[V]);
}
}