zoukankan      html  css  js  c++  java
  • nyist oj 311 全然背包 (动态规划经典题)

    全然背包

    时间限制:3000 ms  |  内存限制:65535 KB
    难度:4
    描写叙述

    直接说题意,全然背包定义有N种物品和一个容量为V的背包。每种物品都有无限件可用。第i种物品的体积是c,价值是w。

    求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。

    假设不能恰好装满背包,输出NO

    输入
    第一行: N 表示有多少组測试数据(N<7)。 
    接下来每组測试数据的第一行有两个整数M。V。 M表示物品种类的数目,V表示背包的总容量。(0<M<=2000,0<V<=50000)
    接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0<c<100000,0<w<100000)
    输出
    相应每组測试数据输出结果(假设能恰好装满背包,输出装满背包时背包内物品的最大价值总和。

    假设不能恰好装满背包,输出NO)

    例子输入
    2
    1 5
    2 2
    2 5
    2 2
    5 1
    例子输出
    NO
    1
    上传者

    ACM_赵铭浩

    动态规划经典题;也有几种思路,最优的思路把01背包问题的第二重循环的顺序改一下,就得到了全然背包的最优解法;

    这个算法使用一维数组,先看伪代码:(引用的背包9讲里面的内容)

    for i=1..N
        for v=0..V
            f[v]=max{f[v],f[v-cost]+weight}

    你会发现,这个伪代码与01背包的伪代码仅仅有v的循环次序不同而已。 为什么这样一改就可行呢?首先想想为什么P01中要依照v=V..0的逆序来循环。

    这是由于要保证第i次循环中的状态f[i][v]是由状态f[i-1] [v-c[i]]递推而来。换句话说。这正是为了保证每件物品仅仅选一次。保证在考虑“选入第i件物品”这件策略时,根据的是一个绝无已经选入第i件物品的 子结果f[i-1][v-c[i]]。而如今全然背包的特点恰是每种物品可选无限件。所以在考虑“加选一件第i种物品”这样的策略时,却正须要一个可能已选入第i种物品的子结果f[i][v-c[i]],所以就能够而且必须採用v=0..V的顺序循环。这就是这个简单的程序为何成立的道理。

    值得一提的是,上面的伪代码中两层for循环的次序能够颠倒。这个结论有可能会带来算法时间常数上的优化。

    这个算法也能够以另外的思路得出。

    比如。将基本思路中求解f[i][v-c[i]]的状态转移方程显式地写出来,代入原方程中,会发现该方程能够等价地变形成这样的形式:

    f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]}

    将这个方程用一维数组实现,便得到了上面的伪代码。

    以下是实现的代码;动态规划的代码都非常easy,最重要的是掌握当中的状态转移方程:

    #include <cstdio>
    #include <cstring>
    #define max(a,b) a>b?

    a:b const int maxn=50001; int dp[maxn]; int main() { int n,m,v,i,j,c,w; scanf("%d",&n); while(n--) { memset(dp,-10000,sizeof(dp));//这里也要注意,在01背包中初始化给的是0,这里要初始化一个比較大的负数 dp[0]=0;//这里也要注意,没有这个就会wa scanf("%d%d",&m,&v); for(i=1;i<=m;i++) { scanf("%d%d",&c,&w); for(j=c;j<=v;j++) dp[j]=max(dp[j],dp[j-c]+w);//状态转移方程也和01背包一致 } if(dp[v]<0) printf("NO "); else printf("%d ",dp[v]); } return 0; }



  • 相关阅读:
    Java-----Excel转HTML
    UI_拖动View
    查找——图文翔解Treap(树堆)
    android 三级菜单 BaseExpandableListAdapter
    New Relic——手机应用app开发达人的福利立即就到啦!
    安卓 下载多线程带进度条
    大数据
    Android学习路线(六)为Android应用加入ActionBar
    JavaScript日期对象使用总结
    经典二叉树
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5167507.html
Copyright © 2011-2022 走看看