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
    */
    
    
  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/12932349.html
Copyright © 2011-2022 走看看