状压dp

总共有 n 个人和 40 种不同的帽子,帽子编号从 1 到 40 。

给你一个整数列表的列表 hats ,其中 hats[i] 是第 i 个人所有喜欢帽子的列表。

请你给每个人安排一顶他喜欢的帽子,确保每个人戴的帽子跟别人都不一样,并返回方案数。

由于答案可能很大,请返回它对 10^9 + 7 取余后的结果。

 

示例 1:

输入:hats = [[3,4],[4,5],[5]]
输出:1
解释:给定条件下只有一种方法选择帽子。
第一个人选择帽子 3,第二个人选择帽子 4,最后一个人选择帽子 5。
示例 2:

输入:hats = [[3,5,1],[3,5]]
输出:4
解释:总共有 4 种安排帽子的方法:
(3,5),(5,3),(1,3) 和 (1,5)

链接:https://leetcode-cn.com/problems/number-of-ways-to-wear-different-hats-to-each-other
思路:

用二进制表示戴帽子情况

故把问题转化为每种帽子可以被哪些人戴

这样可能情况只有

2的10次方

 

class Solution {
public:
    int numberWays(vector<vector<int>>& hats) {
        int n=hats.size();
        vector<int> dp(1<<n,0);
        vector<int> s[41];
        dp[0]=1;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<hats[i].size();j++)
            {
                s[hats[i][j]].push_back(i);
            }
        }
        for(int i=1;i<=40;i++)//帽子
        {
            for(int j=(1<<n)-1;j>0;j--)//状态 111111111,跟背包问题一样的模型
            {
                for(int k=0;k<s[i].size();k++)//遍历这种帽子可以带的人
                {
                    int Judge=1<<s[i][k];
                    if(j&Judge)//可以这个人当前戴了帽子,加上之前状态
                    {
                        dp[j]=(dp[j-Judge]+dp[j])%1000000007;
                    }

                }
            }

        }
        return dp[(1<<n)-1];


    }
};

 

posted @ 2020-05-03 08:37  ___Charles  阅读(122)  评论(0)    收藏  举报