hdu5543

背包贪心,比赛时只考虑了两端都出头,其实还有不出头和只有一端出头的情况,这里的u的数量就是对应上面三种情况

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000+10;
typedef long long int ll;
typedef pair<ll,ll> pp;
pp a[maxn];
int n,l,t;
ll dp[4*maxn][5];//因为防止浮点数,所以要开到4000
int main()
{
    while(~scanf("%d",&t))
    {
        for(int ii=1; ii<=t; ii++)
        {
            ll maxi=0;
            scanf("%d%d",&n,&l);
            l=l*2;//防止浮点数
            for(ll i=0; i<n; i++)
            {
                scanf("%lld%lld",&a[i].first,&a[i].second);
                a[i].first=a[i].first*2;//同上
                maxi=max(maxi,a[i].second);//防止一个
            }
            memset(dp,0,sizeof(dp));
            for(int i=0; i<n; i++)
                for(int j=l; j>=a[i].first/2; j--)
                {
                    for(int u=0; u<=2; u++)
                    {//只找组合,并不需要排序
                        if(u>0)
                        {
                            if(j>=a[i].first) dp[j][u]=max(dp[j][u],dp[j-a[i].first][u]+a[i].second);
                            dp[j][u]=max(dp[j][u],dp[j-a[i].first/2][u-1]+a[i].second);//最神奇的地方,每种最终容器盛满只能从0到1经过1次,从0到2经过两次,正好对应几次出头
                        }
                        else if(j>=a[i].first) dp[j][u]=max(dp[j][u],dp[j-a[i].first][u]+a[i].second);
                    }
                }
                printf("Case #%d: ",ii);
                printf("%lld\n",max(maxi,dp[l][2]));

        }

    }
    return 0;
}

 

posted on 2017-04-06 21:50  发牌员  阅读(208)  评论(0编辑  收藏  举报

导航