zoukankan      html  css  js  c++  java
  • 【背包问题】

    【01背包】

    描述:给定物品总数(n),背包承重能力(m),物品价值(v[i]),物品重量(w[i]),求满足不超过背包承重能力的物品最大价值,每种物品只有一件。
    解法:
    (f[j])表示物品总重为(j)时,物品的最大总价值。
    那么转移方程为

    for(int i=1;i<=n;++i){//枚举物品
    	for(int j=m;j>=w[i];--j){//枚举物品总重
    	    f[j]=max(f[j],f[j-w[i]]+v[i]);
    	}
    }return f[m];
    

    正确性:每次转移时(f[j-w[i]])尚未被物品(i)尝试更新,故每个状态最多被当前物品更新一次。

    【完全背包】

    描述:给定物品种类数(n),背包承重能力(m),物品价值(v[i]),物品重量(w[i]),求满足不超过背包承重能力的物品最大价值,每种物品有无限件。
    解法:
    (f[j])表示物品总重为(j)时,物品的最大总价值。
    那么转移方程为

    for(int i=1;i<=n;++i){
    	for(int j=w[i];j<=m;++j){
    		f[j]=max(f[j],f[j-w[i]]+v[i]);
    	}
    }return f[m];
    

    正确性:每次转移时(f[j-w[i]])已经被物品(i)尝试更新,故每个状态会被物品尽可能多地更新(填满为止)。

    【多重背包】

    描述:给定物品种类数(n),背包承重能力(m),物品价值(v[i]),物品重量(w[i]),求满足不超过背包承重能力的物品最大价值,每种物品有(c[i])件。
    解法:
    (f[j])表示物品总重为(j)时,物品的最大总价值。
    那么转移方程为

    for(int i=1;i<=n;++i){
        for(int k=1;k<=c[i];++k){
            for(int j=m;j>=w[i];--j){
                f[j]=max(f[j],f[j-w[i]]+v[i]);
            }
        }
    }return f[m];
    

    正确性:每种物品都以01背包的方式尝试更新了(c[i])件。

    【多重背包的优化】

    ①二进制优化
    将多重背包拆分成(log c[i])块使得这些块的组合能表达(1~c[i])所有的数值。

    for(int i=1;i<=n;++i){
    	scanf("%d%d%d",&v[0],&w[0],&c[0]);
        for(int j=1;j<=c[0];j<<=1){
            v[++cnt]=v[0]*j;
            w[cnt]=w[0]*j;
            c[0]-=j;
        }if(c[0]) v[++cnt]=v[0]*c[0],w[cnt]=w[0]*c[0];
    }for(int i=1;i<=cnt;++i){
        for(int j=m;j>=w[i];--j){
            f[j]=max(f[j],f[j-w[i]]+v[i]);
        }
    }return f[m];
    

    ②单调队列优化
    这个会了二进制优化就没必要学了吧,背包问题用这个优化不了多少。

    【分组背包】

    描述:给定物品个数(n),背包承重能力(m),物品价值(v[i]),物品重量(w[i]),求满足不超过背包承重能力的物品最大价值,每种物品属于(c[i])组,每组物品中只能选一个。
    解法:
    (f[j])表示物品总重(j)时,物品的最大总价值
    那么转移方程为

    int x,p[MAXC][MAXN];
    for(int i=1;i<=n;++i) scanf("%d%d%d",&v[i],&w[i],&x),p[x][++p[x][0]]=i;
    for(int i=1;i<=MAXC;++i){
        for(int j=m;j>=0;--j){
            for(int k=1;k<=p[i][0];++k){
                if(w[p[i][k]]<=j) f[j]=max(f[j],f[j-w[p[i][k]]]+v[p[i][k]]);
            }
        }
    }
    

    正确性:每个组别的每件物品在互相冲突的前提下进行更新。

    泛化物品

    描述:(v[i])(w[i])成函数关系。
    解法:按照分组背包方式枚举(w[i])求解即可。

    混合背包

    描述:每种物品可能可以多次使用,也可以只有一个,有的可以无限使用,有的(v[i])(w[i])成函数关系。
    解法:分类讨论即可。

    用先进的科学技术与思想文化武装起来的人民,是一个国家最巨大的生产力,是一个社会最强大的推动力,是一个民族最坚实的自信力,是一支军队最可靠的战斗力。 ——A·H
  • 相关阅读:
    docker从容器里面拷文件到宿主机或从宿主机拷文件到docker容器里面
    maven构建的项目相关的命令
    gradle build文件中文乱码解决
    adobe acrobat看PDF文档显示字体发虚,有毛刺的解决办法
    Jenkins 用Tomcat部署War出现 反向代理设置有误
    变量 $cfg['TempDir'] (./tmp/)无法访问。phpMyAdmin无法缓存模板文件,所以会运行缓慢。
    phpMyAdmin配置文件中的密文(blowfish_secret)太短
    phpmyadmin报错:mysqli_real_connect(): (HY000/2002): No such file or directory 错误正确解决方法
    Gradle编译设置编码格式
    redis中的hash
  • 原文地址:https://www.cnblogs.com/AH2002/p/9591996.html
Copyright © 2011-2022 走看看