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
    */
    
    
  • 相关阅读:
    DataStructure期末复习小tips
    MediaPlayer
    Java中Calendar的用法
    C++小tips
    函数返回局部变量的问题
    framebuffer
    MTK gpio adb 控制 和 查看中断INDEX
    emmc
    No 'Access-Control-Allow-Origin' header is present on the requested resource.解决方法(亲测有效)
    JavaScript的Promise必须要会的几个点
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/12932349.html
Copyright © 2011-2022 走看看