现在的位置: 首页 > 综合 > 正文

[hoj]1485 A Good Helper[背包问题]

2018年03月17日 ⁄ 综合 ⁄ 共 1035字 ⁄ 字号 评论关闭
#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

文章来源,内容有改正.

抱歉!评论已关闭.