您的位置:首页 > 其它

poj3093(背包最大容量)

2016-02-29 23:30 190 查看
链接:点击打开链接

题意:给定一个容量为D的背包和V件物品各自的体积,求有多少种方法使得背包再也装不下任何物品

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int w[1005],dp[1005],sum[1005];
int main(){
int t,n,v,i,j,k,ans,tmp;
scanf("%d",&t);                             //当前容量装不下则表示没装的物品中体积最小的
for(k=1;k<=t;k++){                          //也装不下,因此枚举最小的物品是哪一个
scanf("%d%d",&n,&v);
memset(dp,0,sizeof(dp));
memset(sum,0,sizeof(sum));
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
sort(w+1,w+n+1);
for(i=1;i<=n;i++)
sum[i]=sum[i-1]+w[i];
if(w[1]>v){                             //最小的也装不下输出0
printf("%d 0\n",k);
continue;
}
ans=0;
dp[0]=1;
for(i=n;i>=1;i--){                      //优化在于从后往前枚举,因为从前往后枚举
tmp=v-sum[i-1];                     //比当前枚举的值大的所有值,每次都会进行
for(j=max(0,tmp-w[i]+1);j<=tmp;j++) //01背包,因此从后枚举时避免了重复进行
ans+=dp[j];
for(j=v;j>=w[i];j--)                //如果当前枚举的值是w[i],答案就是装满
dp[j]+=dp[j-w[i]];                  //sum-w[i]+1~sum的所有总数的和,又因为
}                                       //要保证当前值是剩下的值中最小的,因此
printf("%d %d\n",k,ans);                //左右边界的容量都减去sum[i-1]
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: