常见的两种经典背包问题
- 完全背包
- 0-1背包
0-1背包问题示例
递归真的不擅长写,我感觉就是很难控制它递归的范围,有可能递归多了,也有可能递归少了
全排列的写法
package 算法练习;
public class 背包01问题 {
static int[] weight=new int[6];
static int[] value=new int[6];
static int[] ans=new int[6];
static int flag=0;
public static void dfs(int weight1,int total)
{
flag=1;
//判断是否是最后一步,最后一步flag是1
for(int j=1;j<=5;j++)
{
if(ans[j]==0&&weight1-weight[j]>=0)
{
flag=0;
break;
}
}
if(flag==1)
{
System.out.println(total);
flag=0;
return;
}
//主要递推在这里
for(int i=1;i<=5;i++)
{
//走过的不能再走
if(ans[i]==1)
{
continue;
}
//没走过,如果也比weight1小的可以走
if(weight1>=weight[i])
{
ans[i]=1;
dfs(weight1-weight[i],total+value[i]);
ans[i]=0;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
weight[1]=2;
weight[2]=2;
weight[3]=6;
weight[4]=5;
weight[5]=4;
value[1]=6;
value[2]=3;
value[3]=5;
value[4]=4;
value[5]=6;
dfs(10,0);
}
}
学习2
动态规划的写法
其中dp[i][j],i表示出现了i件物品,前面的物品可拿可不拿,j表示当前剩余的容量,
例如dp[3][5]它不一定一,二,三件物品都选,它受限于容量有可能只能选了第一件,第一件拿了容量就没了,并且它是3件物品可选,第三件必选,容量为5的最大值。
dp[2][5]表示2件物品可选,容量为5的最大值
因此dp[3][5]是取决于
- 可以取走第2件时候的最大值,不考虑第三件,就是dp[3][5]的上一个数dp[2][5]
- 第三件如果能选择,必选时候的最大值,dp[2][0]+v[2]
然后去比较这两个值
这也是一种典型的规划问题,所以可以做出表格,通过表格可以发现,也是从左往右,从上往下进行遍历
每个格子代表着那种情况的value的最大值,它取决于,两个值
dp[j][i]=Math.max((dp[j-1][i-weight[j]])+value[j],dp[j-1][i]);
- 其中一个元素是同一列的上一个值,表示的是。在一定的容量下,可能拿的越少,value值越大,所以同一列,上面的值有可能比下面拿多的值小
- 另外拿走多件的情况的最大value值
package 算法练习;
public class 背包01问题动态规划 {
static int[] weight=new int[4];
static int[] value=new int[4];
static int[][] dp=new int[4][11];
public static void main(String[] args) {
// TODO Auto-generated method stub
weight[1]=5;
weight[2]=6;
weight[3]=4;
value[1]=20;
value[2]=10;
value[3]=12;
int rong=10;
//i是称重量,j是可选几件物品
for(int i=1;i<=10;i++)
for(int j=1;j<=3;j++)
{
//如果能把value加上,就比较一下,加上的情况好,还是不加的情况好
if(i-weight[j]>=0)
{
//拆分拿的value最大的值+比较表格中同一列前一行value的最大值
dp[j][i]=Math.max((dp[j-1][i-weight[j]])+value[j],dp[j-1][i]);
}
//不能把value加上,直接用上一个值,就是不考虑这个value[i]
else
{
dp[j][i]=dp[j-1][i];
}
}
for(int i=1;i<=3;i++)
{for(int j=1;j<=10;j++)
{
System.out.print(dp[i][j]+" ");
}
System.out.println();}
}
}
完全背包问题
代码实现
package 算法练习;
public class 完全背包问题 {
static int[] weight=new int[4];
static int[] value=new int[4];
static int[][] dp=new int[3][11];
public static void main(String[] args) {
// TODO Auto-generated method stub
weight[1]=5;
weight[2]=7;
value[1]=5;
value[2]=8;
int rong=10;
for(int i=1;i<=10;i++)
for(int j=1;j<=2;j++)
{
//j上限的体重可以有几种情况
//从1个开始
int k=1;
if(i>=weight[j])
{
//cen先赋值
int cen=dp[j-1][i];
//先让它等于上一个值
dp[j][i]=cen;
while(weight[j]*k<=i)
{
int ans=dp[j-1][rong-weight[j]*k]+value[j]*k;
//
if(ans>cen)
{
dp[j][i]=ans;
cen=ans;
}
k=k+1;
}
}
else
{
dp[j][i]=dp[j-1][i];
}
}
for(int i=1;i<=2;i++)
{for(int j=1;j<=10;j++)
{
System.out.print(dp[i][j]+" ");
}
System.out.println();}
}
}
贪心算法