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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章