牛客練習賽61 C.四個選項(01揹包+哈希壓狀態)

題目

有一些條件,首先四個選項的數量必須分別爲 na,nb,nc,nd(保證na+nb+nc+nd=12)。

其次有 m(0<=m<=1e3) 個額外條件,分別給出兩個數字 x,y,代表第 x 個題和第 y 個題的答案相同(1<=x,y<=12)。

現在你的老師想知道,有多少種可行的方案安排答案。

思路來源

https://ac.nowcoder.com/discuss/405216?type=101&order=0&pos=1&page=1

題解

dp[i][x1][x2][x3][x4]爲枚舉到第i個物品,四個揹包被裝填的體積分別爲x1,x2,x3,x4的方案數,直接枚舉填哪個揹包轉移即可。

由於數據量較小,dfs也是可以的。

如果數據量再大一點,可以把所有揹包的體積的所有狀態哈希一下,變成一個二維dp,再滾動一下第一維即可。


“比方說四個揹包的體積和是200, 你總不能開[200][200][200][200]這樣的數組吧,即使滾動一維代價也好大,

但是所有可能的元組(a,b,c,d)至多50*50*50*50個,所以可以把這些元組哈希一下。”

 

dfs做法顯然,本題試一下哈希壓狀態的寫法,之前沒這麼搞過。

代碼

#include <bits/stdc++.h>
using namespace std;
const int N=4;
int m,x,y;
int dp[N*N*N*N],a[13],tot,cnt,now[4],b[4],nex,pre;
bool vis[13];
vector<int>e[13];
void dfs(int u){
    cnt++;
    vis[u]=1;
    for(auto &v:e[u]){
        if(!vis[v])dfs(v);
    }
}
int g(int a[4]){
    int ans=0;
    for(int i=0;i<4;++i){
        ans=ans*(now[i]+1)+a[i];
    }
    return ans;
}
int main(){
    for(int i=0;i<4;++i){
        scanf("%d",&now[i]);
    }
    scanf("%d",&m);
    while(m--){
        scanf("%d%d",&x,&y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    for(int i=1;i<=12;++i){
        if(!vis[i]){
            cnt=0;
            dfs(i);
            a[++tot]=cnt;
        }
    }
    dp[0]=1;
    int cal=0;
    for(int i=1;i<=tot;++i){
        for(int j=now[0];j>=0;j--){
            for(int k=now[1];k>=0;k--){
                for(int l=now[2];l>=0;l--){
                    for(int m=now[3];m>=0;m--){
                        b[0]=j;b[1]=k;b[2]=l;b[3]=m;
                        nex=g(b);
                        if(b[0]>=a[i])b[0]-=a[i],pre=g(b),dp[nex]+=dp[pre],b[0]+=a[i];
                        if(b[1]>=a[i])b[1]-=a[i],pre=g(b),dp[nex]+=dp[pre],b[1]+=a[i];
                        if(b[2]>=a[i])b[2]-=a[i],pre=g(b),dp[nex]+=dp[pre],b[2]+=a[i];
                        if(b[3]>=a[i])b[3]-=a[i],pre=g(b),dp[nex]+=dp[pre],b[3]+=a[i];
                    }
                }
            }
        }
    }
    printf("%d\n",dp[g(now)]);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章