UESTC 1218 Pick The Sticks (2015 CCPC)

题目链接

题意就是给你一块长为l的木板,然后有n个木棍,木棍有长度,有价值,可以放在木板上,只要它超出木棍的的长度不超过他自己长度的二分之一,它就可以放上去。

看大家对揹包问题的的理解,很明显加一维状态,表示放在边缘没。

下面是代码
细节就是揹包边缘的处理

#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#define LL long long
using namespace std;

LL dp[2][8010][3];
LL w[4005],v[4005];

int main()
{
    int t,kase = 1;
    scanf("%d",&t);
    while(t--){
        memset(dp,0,sizeof(dp));
        int l,n;
        scanf("%d%d",&n,&l);
        l *= 2;
        for(int i=0;i<n;i++){
            scanf("%lld%lld",&w[i],&v[i]);
            w[i] *= 2;
        }
        int now = 1 , pre = 0;
        for(int i=0;i<n;i++){

            for(int j=0;j<=l;j++){
                dp[now][j][0] = dp[pre][j][0];
                dp[now][j][1] = dp[pre][j][1];
                dp[now][j][2] = dp[pre][j][2];
            }

            for(int j=l;j>=w[i];j--){
                dp[now][j][0] = max(dp[pre][j-w[i]][0] + v[i],dp[now][j][0]);
                dp[now][j][1] = max(dp[pre][j-w[i]][1] + v[i],dp[now][j][1]);
                dp[now][j][2] = max(dp[pre][j-w[i]][2] + v[i],dp[now][j][2]);
            }

            for(int j=l;j>=w[i]/2;j--){
                dp[now][j][1] = max(dp[now][j][1],dp[pre][j-(w[i]/2)][0] + v[i]); // 这里很关键
                dp[now][j][2] = max(dp[now][j][2],dp[pre][j-(w[i]/2)][1] + v[i]); // 这里很关键
            }
            swap(now,pre);
        }
        LL ans = dp[pre][l][0];
        ans = max(ans,dp[pre][l][1]);
        ans = max(ans,dp[pre][l][2]);
        for(int i=0;i<n;i++) ans = max(ans,v[i]);
        printf("Case #%d: ",kase++);
        printf("%lld\n",ans);

    }
    return 0;
}

总之这题算是2015年CCPC的铜牌题。
加油!!!!!!

发布了40 篇原创文章 · 获赞 7 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章