hdu3535AreYouBusy(分組揹包問題)

常見的有三種,
一,每組最多取一個,
一維數組的僞代碼
for 所有的組k
for v = V to 0
for 所有的i屬於組k
f[v] = max{f[v], f[v -c[i]] + w[i]}
注意順序不能寫反,因爲要限制每組最多取一個
二,每組任意取
既然上面的順序是限制每組最多取一個,那調換一下順序即可,其實就是01揹包。
一維數組的僞代碼
for 所有的組k
for 所有的i屬於組k
for v = V to 0
f[v] = max{f[v], f[v -c[i]] + w[i]}
三,每組至少取一個
沒見過一維的僞代碼,
dp[ki}[i}表示當前不選,dp[ki-1}[i-b[ki}}+c[ki}表示這是第一個選,
dp[ki}[i-b[ki}}+c[ki}表示再在這一組中選。
初始化時記得ki==0,賦值0,
其他賦值-inf
dp[ki}[i}=max(dp[ki}[i},dp[ki-1}[i-b[ki}}+c[ki},dp[ki}[i-b[ki}}+c[ki})
//分開寫時要注意順序!!!

下面這道題是這三種的綜合,由於第三種情況要用二維寫,所以就都用二維寫。

if(type==0) 
    for(int i=0;i<=T;i++) dp[ni][i]=-inf;
else
    for(int i=0;i<=T;i++) dp[ni][i]=dp[ni-1][i];

上面代碼是將狀態從上一個組傳遞到當前組。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int inf=0x7fffffff;
int dp[102][102];
int main(int argc, char const *argv[])
{
    int N,T;
    while(scanf("%d %d",&N,&T)==2){
        ms(dp);
        for(int ni=1;ni<=N;ni++)
        {
            int num,type;
            scanf("%d %d",&num,&type);
            if(type==0) for(int i=0;i<=T;i++) dp[ni][i]=-inf;
            else for(int i=0;i<=T;i++) dp[ni][i]=dp[ni-1][i];
            if(type==0){//至少選一個
                while(num--){
                    int c,g;
                    scanf("%d %d",&c,&g);
                    for(int i=T;i>=c;i--)
                    {
                        dp[ni][i]=max(dp[ni][i],dp[ni][i-c]+g);
                        dp[ni][i]=max(dp[ni][i],dp[ni-1][i-c]+g);
                    }
                }
            }
            else if(type==1){//至多選一個
                while(num--){
                    int c,g;
                    scanf("%d %d",&c,&g);
                    for(int i=T;i>=c;i--)
                    {
                        dp[ni][i]=max(dp[ni][i],dp[ni-1][i]);
                        dp[ni][i]=max(dp[ni][i],dp[ni-1][i-c]+g);
                    }
                }
            }
            else{//隨意
                while(num--){
                    int c,g;
                    scanf("%d %d",&c,&g);
                    for(int i=T;i>=c;i--)
                    {
                        dp[ni][i]=max(dp[ni][i],dp[ni-1][i]);
                        dp[ni][i]=max(dp[ni][i],dp[ni][i-c]+g);
                        dp[ni][i]=max(dp[ni][i],dp[ni-1][i-c]+g);
                    }
                }
            }
        }
        if(dp[N][T]<0) puts("-1");
        else printf("%d\n",dp[N][T] );
    }
    return 0;
}
發佈了110 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章