zoukankan      html  css  js  c++  java
  • 背包的几个问题

    1271:【例9.15】潜水员

    二位费用的背包

    背包容量 氧气氮气的体积

    背包费用 罐子的重量

    求费用最小值

    倒着for两维体积,原因是如果正着for,可能一件物品多次放到背包里

    1295:装箱问题

    状压如下,分析复杂度:n<=30,O((1<<30 ) * 30)=O(2e9 *30)= 6e10

    肯定会T的!

    for(int i=0;i<=(1<<n);i++){//2e9
    		int ans0=0;int t=i;
    		int num=n;while(t && num){//30
    			if(t&1)	ans0+=ti[num];
    			t/=2;
    			num--;
    		}
    		if(ans0 <= v && ans0>ans)	ans=ans0;
    	}
    	ans=v-ans;
    	cout << ans <<endl;
    

    二位数组如下

    cin>>v>>n;
    	for(int i=1;i<=n;i++)	cin>>ti[i];
    	for(int i=1;i<=n;i++){
    		for(int j=v;j>=ti[i];j--){
    			if(f[i-1][j-ti[i]]+ti[i] <= v)
    			f[i][j]=max(f[i][j],f[i-1][j-ti[i]]+ti[i]);
    		}
    	}
    	for(int i=1;i<=n;i++)	ans=max(ans,f[i][v]);
    	ans=v-ans;
    	cout<<ans<<endl;
    

    然鹅错了

    滚动数组如下

    cin>>v>>n;
    for(int i=1;i<=n;i++)	cin>>ti[i];
    for(int i=1;i<=n;i++){
    	for(int j=v;j>=ti[i];j--){
    		//if(f[j-ti[i]]+ti[i] <= v)
    		f[j]=max(f[j],f[j-ti[i]]+ti[i]);
    
    		if(f[j] > ans && f[j] < v)	ans=f[j];
    	}
    }
    //ans=f[v];
    ans=v-ans;
    cout<<ans<<endl;
    

    是错的,错误答案和二位数组一样

    另一个如下

    cin>>v>>n;
    for(int i=1;i<=n;i++)	cin>>ti[i];
    for(int i=1;i<=n;i++){
    	for(int j=v;j>=ti[i];j--){
    		if(f[j-ti[i]]+ti[i] <= v)
    		f[j]=max(f[j],f[j-ti[i]]+ti[i]);
    		//if(f[j] > ans && f[j] < v)	ans=f[j];
    	}
    }
    ans=f[v];
    ans=v-ans;
    cout<<ans<<endl;
    

    这便对了。是1维的,不记录无用状态的一维的。

    对于1、2维,我是这么想的:如果是2维,意味着第i个物品只能使用前i个物品的状态,

    如果是1维,第i 个物品还能使用同样是第i 个物品,但是体积更小的状态。但是这样可能会出现第i个物品选两次的情况不是吗?但是如果倒着枚举就不会了(hh我就是倒着枚举的)

    哦,好像应该这么解释:如果是一维的,那么第i 个物品相当于使用的是前1~i-1的所有物品的状态,所以会更优。

    但是根据这个,我们可以给二维的程序加一句:

    f[i][j]=max(f[i][j],f[i-1][j]);

    便可达到同一维数组一样的效果。

    然鹅还不对

    经过调试,我发现了 问题所在:

    1.j应该枚举到0,而不是枚举到ti[i] ,这样才能正确的顺延

    2.其实if(f[j-ti[i]]+ti[i] <= v) 这一句是没用的,因为j的范围和f [i] [j]的范围是一样的,既然j<v,f [i] [j] 也就不会大于v了

    最终的二维代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    using namespace std;
    
    
    int v,n,ti[33];
    int ans;
    int f[33][20010];
    int main()
    {
    	
    	cin>>v>>n;
    	for(int i=1;i<=n;i++)	cin>>ti[i];
    	for(int i=1;i<=n;i++){
    		for(int j=v;j>=0;j--){
    			f[i][j]=max(f[i][j],f[i-1][j]);
    			if(j >= ti[i])
    				f[i][j]=max(f[i][j],f[i-1][j-ti[i]]+ti[i]);
    		}
    	}
    	ans=f[n][v];
    	ans=v-ans;
    	cout<<ans<<endl;
    	
    	
    	return 0;
    }
    /*
    10 3
    1
    5
    7
    */
    
    
  • 相关阅读:
    实用机器学习 跟李沐学AI
    Explicitly drop temp table or let SQL Server handle it
    dotnettransformxdt and FatAntelope
    QQ拼音输入法 禁用模糊音
    (技术八卦)Java VS RoR
    Ruby on rails开发从头来(windows)(七)创建在线购物页面
    Ruby on rails开发从头来(windows)(十三)订单(Order)
    Ruby on rails开发从头来(windows)(十一)订单(Order)
    新员工自缢身亡,华为又站到了风口浪尖
    死亡汽油弹(Napalm Death)乐队的视频和来中国演出的消息
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/12932349.html
Copyright © 2011-2022 走看看