[狀壓dp]leeccode1434:每個人戴不同帽子的方案數(hard)

algsup發表於2021-01-02

題目:

1434. 每個人戴不同帽子的方案數


題解:

  • 思路:狀壓dp
  • 解法:由於本人剛學習壓狀dp,且在《演算法競賽進階指南》上學習了位運算相關的知識,做了兩個狀壓dp的題,思路是學題解的,這裡貼一下,記錄下吧。
    在這裡插入圖片描述
    在這裡插入圖片描述

程式碼如下:

class Solution {
public:
    //思路:狀壓dp
    int numberWays(vector<vector<int>>& hats) {
        int maxHatId=0,n=hats.size(),mod=1000000007;

        // 尋找最大序號帽子的id,便於返回dp[maxHatId][2^n-1]作答
        for(int i=0;i<n;++i){
            for(int h:hats[i]){
                maxHatId=max(maxHatId,h);
            }
        }

        // 對於每一頂帽子 h,hatToPerson[h] 中儲存了喜歡這頂帽子的所有人,方便進行動態規劃
        vector<vector<int>> hatToPerson(maxHatId+1);
        for(int i=0;i<n;++i){
            for(int h:hats[i]){
                hatToPerson[h].push_back(i);
            }
        }

        // dp[i][state]表示我們處理了前i頂帽子,並且已經被分配帽子的人狀態為state的方案數
        vector<vector<int>> dp(maxHatId+1,vector<int>(1<<n));
        // 邊界條件,0個帽子分配給0個人,這也是一種方案數
        dp[0][0]=1;
        for(int i=1;i<=maxHatId;++i){
            for(int state=0;state<(1<<n);++state){
                // 如果第i頂帽子沒有分配給任何人,那麼前i-1頂帽子對應的分配狀態就是state,而dii頂帽子對人的狀態不會發生任何改變
                dp[i][state]=dp[i-1][state];
                for(int j:hatToPerson[i]){
                    // 第i頂帽子戴在第j個人的頭上,因此加上前i−1頂帽子對應的分配狀態中,第j個人沒有被分配帽子,而其它人的分配狀態不變。
                    if(state&(1<<j)){
                        dp[i][state]+=dp[i-1][state^(1<<j)];
                        dp[i][state]%=mod;
                    }
                }
            }
        }

        //maxHatId頂帽子分配給n個人的方案數
        return dp[maxHatId][(1<<n)-1];
    }
};

相關文章