您的位置:首页 > 其它

nyoj311 完全背包

2016-04-04 18:44 148 查看
NYOJ311

   


完全背包

时间限制: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




    有时候完全背包问题,可以看成是图(带权有向图),初始时每个点之间的距离为INF(-INF) ,通过不断的加点更新距离( 两点之间加点(路径)来更新路径) ,得到,最长或最短路径。

----------------------------------------------[b]-----------------------------------------------------------------------------------------------------------[/b]

    小技巧:

     一般我们给dp进行初始化的时候

      for(i=1;i<=v;i++)
dp[i] = -INF;

     还有更简便的方法 

     memset(dp , -100 ,sizeof(dp));

     dp[i]  不是-100 呦,虽然不知道为什么 ,测了一下是-1667457892  足够的小!!比  -  1<<30 还小!



---自己写的

#include<stdio.h>
#define INF 1000000
int main()
{
int m,v,c,w,n,i,j;
int dp[50005];
int a,b;

scanf("%d",&n);
while(n--)
{

scanf("%d %d",&m,&v);
dp[0] = 0; //细心
for(i=1;i<=v;i++)
dp[i] = -INF;
for(i = 0;i<m;i++)
{
scanf("%d %d",&a,&b);

for(j = a;j<=v;j++)
{
dp[j] = dp[j]>dp[j-a]+b?dp[j]:dp[j-a]+b;
}
}

if(dp[v] <0)printf("NO\n");
else
printf("%d\n",dp[v]);
}

return 0;
}

---最优答案

#include<stdio.h>
#include<string.h>
#define max(a,b) (a)>(b)?(a):(b)
int main()
{
int n,m,v,i,j,d[50005],a,b;
scanf("%d",&n);
while(n--)
{
scanf("%d%d",&m,&v);
memset(d,-100,sizeof(d));
d[0]=0; //细心 for(i=0;i<m;i++){scanf("%d%d",&a,&b);for(j=a;j<=v;j++)d[j]=max(d[j-a]+b,d[j]);}if(d[v]<0) printf("NO\n");else printf("%d\n",d[v]);}return 0;}



对了还有一点要说一下,这种推法超时啦!(输入完后整体后推的)

dp[0] = 0;
for(i=1;i<=v;i++)
dp[i] = -INF;
for(i=1;i<=v;i++)
for(j=0;j<m;j++)
if(i>=M[j][0])
dp[i] = dp[i]>dp[i-M[j][0]]+M[j][1]?dp[i]:dp[i-M[j][0]]+M[j][1];
}


  


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: