背包问题+贪心算法

常见的两种经典背包问题

  • 完全背包
  • 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]是取决于

  1. 可以取走第2件时候的最大值,不考虑第三件,就是dp[3][5]的上一个数dp[2][5]
  2. 第三件如果能选择,必选时候的最大值,dp[2][0]+v[2]
    然后去比较这两个值

这也是一种典型的规划问题,所以可以做出表格,通过表格可以发现,也是从左往右,从上往下进行遍历
每个格子代表着那种情况的value的最大值,它取决于,两个值

dp[j][i]=Math.max((dp[j-1][i-weight[j]])+value[j],dp[j-1][i]);
  1. 其中一个元素是同一列的上一个值,表示的是。在一定的容量下,可能拿的越少,value值越大,所以同一列,上面的值有可能比下面拿多的值小
  2. 另外拿走多件的情况的最大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();}
	}

}

贪心算法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值