#include <cstdio>
#include <cstring>
int f[1001];
int max(int a,int b)
{
return (a>b?a:b);
}
void swap(int &a,int &b)//原文swap函数疑有误,此处做了改正
{
int c = a;
a = b;
b = c;
}
int main()
{
int i,j,m,n,x,v[1001],big=1,total,tmp;
while (scanf("%d %d",&m,&n)!=EOF)//两人limit
{
memset(f,0,sizeof(f));
scanf("%d",&x);//包裹数
total=0;//总重量
for (i=1;i<=x;i++)
{
scanf("%d",&v[i]);
if (v[i]>v[big]) big=i;//index标记最大
total+=v[i];
}
swap(v[big],v[x]);
for (i=1;i<=x;i++)
{
tmp=f[m];//tmp用来保存f[i-1,j]
for (j=m;j>=v[i];j--)//依然是做了倒序降维处理
f[j]=max(f[j-v[i]]+v[i],f[j]);
}
//第二个人就不用dp了,直接看总和就可以判断能不能搬走
//只需要dp找出第一个人所能搬走的最大重量,不一定把背包装满
//f[i]可以表示将物品装入容量为i的背包的最大总体积
//特殊之处在于,value和capacity是同一个,当然需要考虑装不进去的情况
//将二维优化为一维,隐藏了取x个物体的枚举
//因此同样是逆序遍历
if ((total-f[m])<=n) printf("Yes\n");//两个人能把全部搬走
else if ((total-v[x]-tmp)<=n) printf("Need a helper\n");//除了最重的能搬走
else printf("No\n");
}
return 0;
}
这仍然是个dp,就是一个简单的背包。
因为牛叉的助手能够搬动任何重量的东西,所以这个强人要专门考虑。在第一次的时候就找出最大的重量放到最后。然后将第一个人做一次01背包,然他去尽量的多的搬东西,然后判断剩下的东西能不能让第二个人来搬,不能的话,判断去除最后一个(即重量最大的)东西后两个人能不能搬。
f[i,j]表示不除最后一个的最大重量,那么f[i-1,j]则表示除了最后一个。
http://blog.sina.com.cn/s/blog_6d6add550100ypqp.html
文章来源,内容有改正.