HDU 5410 CRB and His Birthday(完全背包+01背包)

题目地址:点击打开链接

思路:把一种物品分为二种物品,它们花的钱相同,一种物品只能取一次,获得的糖果为a[i]+b[i],另一种物品能取无数次,获得的糖果为a[i],当二种物品取到时,第一种物品物品肯定已经取了,因为花的钱一样,第一种获得的糖果多,这样就转化为完全背包和01背包

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int w[1010],a[1010],b[1010],dp[2010];

int main()
{
    int t,n,m,i,j;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&m,&n);
        for(i=1; i<=n; i++)
        {
            scanf("%d%d%d",&w[i],&a[i],&b[i]);
        }
        for(i=1; i<=n; i++)
        {
            for(j=m; j>=w[i]; j--)
            {
                dp[j] = max(dp[j],dp[j-w[i]] + a[i] + b[i]);
            }
            for(j=w[i]; j<=m; j++)
            {
                dp[j] = max(dp[j],dp[j-w[i]] + a[i]);
            }
        }
        printf("%d\n",dp[m]);
    }
}

超时代码:

#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

int dp[1001][2010];
int w[1001],a[1001],b[1001];

int main()
{
    int t,m,n,i,j,max1,k;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&m,&n);
        for(i=1; i<=n; i++)
        {
            scanf("%d%d%d",&w[i],&a[i],&b[i]);
        }
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=m; j++)
            {
                max1 = dp[i-1][j];
                for(k=1; k*w[i]<=j; k++)
                {
                    if(dp[i-1][j-k*w[i]]+k*a[i]+b[i] > max1)
                    {
                        max1 = dp[i-1][j-k*w[i]]+k*a[i]+b[i];
                    }
                }
                dp[i][j] = max1;
            }
        }
        printf("%d\n",dp[n][m]);
    }
    return 0;
}

错误代码1:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int w[1010],a[1010],b[1010],dp[2010];

int main()
{
    int t,n,m,i,j,max1;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&m,&n);
        for(i=1; i<=n; i++)
        {
            scanf("%d%d%d",&w[i],&a[i],&b[i]);
        }
        for(i=1; i<=n; i++)
        {
            max1 = dp[m];
            for(j=m; j>=w[i]; j--)
            {
                dp[j] = max(dp[j],dp[j-w[i]] + a[i] + b[i]);
            }
            if(max1 != dp[m])
            {
                for(j=w[i]; j<=m; j++)
                    dp[j] = max(dp[j],dp[j-w[i]] + a[i]);
            }
        }
        printf("%d\n",dp[m]);
    }
}

错误代码2:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int w[1010],a[1010],b[1010],dp[2010];

int main()
{
    int t,n,m,i,j,max1;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&m,&n);
        for(i=1; i<=n; i++)
        {
            scanf("%d%d%d",&w[i],&a[i],&b[i]);
        }
        for(i=1; i<=n; i++)
        {
            max1 = dp[w[i]];
            for(j=m; j>=w[i]; j--)
            {
                dp[j] = max(dp[j],dp[j-w[i]] + a[i] + b[i]);
            }
            if(max1 != dp[w[i]])
            {
                for(j=w[i]; j<=m; j++)
                    dp[j] = max(dp[j],dp[j-w[i]] + a[i]);
            }
        }
        printf("%d\n",dp[m]);
    }
}

超时代码直接枚举每种可能,直接超时,不会判断复杂度,一顿乱搞,错误代码错误的原因是,认为某件物品最小容量的都放了,大的肯定放了,或者最大容量都放了,最小容量肯定也放了,其实他们是没有关系的,大致原因就是放这个物品时会导致花费高同时性价比比这个物品高的物品剔除出去,虽然对小的没影响,对大的会有影响,或者来了一个花费高但同时性价比高的物品,大的会要这个物品,而小的不会要这个物品,因为它本身的费用太小

你可能感兴趣的:(HDU 5410 CRB and His Birthday(完全背包+01背包))