zoukankan      html  css  js  c++  java
  • 背包的第k优解[动态规划]

    From easthong
    背包的第k优解
     
         
         
      描述 Description  
      DD 和好朋友们要去爬山啦!他们一共有 K 个人,每个人都会背一个包。这些包的容量是相同的,都是 V。可以装进背包里的一共有 N 种物品,每种物品都有给定的体积和价值。

    在 DD 看来,合理的背包安排方案是这样的:

      1. 每个人背包里装的物品的总体积恰等于包的容量。
      2. 每个包里的每种物品最多只有一件,但两个不同的包中可以存在相同的物品。
      3. 任意两个人,他们包里的物品清单不能完全相同。

    在满足以上要求的前提下,所有包里的所有物品的总价值最大是多少呢?
         
         
      输入格式 Input Format  
      第一行有三个整数:K、V、N。

    第二行开始的 N 行,每行有两个整数,分别代表这件物品的体积和价值。
         
         
      输出格式 Output Format  
      只需输出一个整数,即在满足以上要求的前提下所有物品的总价值的最大值。
         
         
      样例输入 Sample Input  
       
         
         
      样例输出 Sample Output  
       
         
         
      时间限制 Time Limitation  
      1s
         
         
      注释 Hint  
      数据范围

    总人数 K<=50。

    每个背包的容量 V<=5000。

    物品种类数 N<=200。

    其它正整数都不超过 5000。

    输入数据保证存在满足要求的方案。
         
         
      来源 Source  
      dd 2007 dp 模拟赛
     
    慢慢啃
    f[j][u]表示空间为j时的第u优解;
     
    性质:加了一个u循环操作的01背包,i表示加入第i个物品则循环顺序从外到里为i->j->u(就是把原本f[j]=max(f[j-w[i]]+v[i],f[j])的位置变成u的循环操作而已);
     
    初始化: 
    f[j][u]=负无穷(u循环操作前要判定f[j-w[i]][1]>=0),f[0][1]=0;
     
    u的循环操作:
    1.已知f[j]=max(f[j-w[i]]+v[i],f[j]),即f[j]有两种取值方案;
    用两个数组st1[u]和st2[u]分别储存f[j-w[i]][u]+v[i]和f[j][u];
    2.因为f[j][u]一定优于f[j][u+1],所以st1[u]一定优于st1[u+1],st2[u]同理,所以只需要比较st1和st2中的元素就可以得到当前可以取到的最优值;
    所以f[i][u]等于st1[tail1]和st2[tail2]中较大的;
    3.因为不能有一样的方案,所以st1[tail1],st2[tail2]中较大的数被f[i][u]取值后,对应的tail++(tail在u循环开始前定义为0或者1);
     
     
    随着j的增大,方案数是树状增多的,但是前u个最优方案一定是在这棵树的某一个分支上,这个分支的父节点一定是某一个阶段的最优方案,就像分封制一样,离最后的最优方案血缘关系越远优秀程度越差,嗯我是这么理解的.....
     
    因为动态规划每一个阶段的方案只和前一个阶段有关,所以可以在输入数据后直接j循环,不需要v[i]w[i]之类存储每一个状态的数组...
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 int k,v,n;
     8 long long f[5010][51]={};
     9 long long st1[5010]={};
    10 long long st2[5010]={};
    11 int main(){
    12     cin>>k>>v>>n;
    13     for(int i=0;i<v;i++){
    14         for(int j=0;j<=k;j++){
    15             f[i][j]=-99999999;
    16         }
    17     }
    18     f[0][1]=0;
    19     for(int i=1;i<=n;i++){
    20         int a,b;
    21         cin>>a>>b;
    22         for(int j=v;j>=a;j--){
    23             if(f[j-a][1]>=0){
    24                 int p1=1,p2=1;
    25                 for(int u=1;u<=k;u++){
    26                     st1[u]=f[j-a][u]+b;
    27                     st2[u]=f[j][u];
    28                     if(st2[p2]>=st1[p1]) f[j][u]=st2[p2++];
    29                     else f[j][u]=st1[p1++];
    30                 }
    31             }
    32         }
    33     }
    34     long long ans=0;
    35     for(int i=1;i<=k;i++){
    36         ans+=f[v][i];
    37     }
    38     cout<<ans<<endl;
    39     return 0;
    40 }
    View Code
     
  • 相关阅读:
    python django 创建app失败 升级sqlite3 或者修改数据库连接为mysql
    Decima json 化
    openpyxl excel操作
    centos添加python虚拟环境
    oracle的参数文件:pfile和spfile
    修改 db_unique_name
    工具 --- Vim
    部署 --- Nginx
    工具 --- Git使用
    django 之(五) --- RESTApi总结
  • 原文地址:https://www.cnblogs.com/137shoebills/p/7783628.html
Copyright © 2011-2022 走看看