题目
游戏中存在两种角色:
好人:该角色只说真话。
坏人:该角色可能说真话,也可能说假话。
给你一个下标从 0 开始的二维整数数组 statements ,大小为 n x n ,表示 n 个玩家对彼此角色的陈述。具体来说,statements[i][j] 可以是下述值之一:
0 表示 i 的陈述认为 j 是 坏人 。
1 表示 i 的陈述认为 j 是 好人 。
2 表示 i 没有对 j 作出陈述。
另外,玩家不会对自己进行陈述。形式上,对所有 0 <= i < n ,都有 statements[i][i] = 2 。
根据这 n 个玩家的陈述,返回可以认为是 好人 的 最大 数目。
提示:
n == statements.length == statements[i].length
2 <= n <= 15
statements[i][j] 的值为 0、1 或 2
statements[i][i] == 2
思路
在leetcode上看见有人说:n<=20 的题目一般是暗示 状态压缩/二进制枚举/回溯,觉得很对,在此记录一下。
我们可以发现,0代表坏,1代表好,2无影响。因此我们只需要用0、1来表示,此时二进制思路应该扑面而来。
数组长度小于15,215也不会出现超时现象,可以进行暴力求解。因此可以将二进制每一位代表1个人的好坏,枚举所有的2n可能性(即每个人好坏的所有可能性)。
对于每一种可能性,找到该可能性中说真话的人,如果他们的判断和这种可能性不符合,则筛去。
最后所有能对应上的情况就是真实情况。
代码
class Solution {
public:
int maximumGood(vector<vector<int>>& statements) {
int maxx = 0;//标记最大值
int len = statements.size();
for(int num=0;num<(1<<len);num++){ //1<<len代表2^len+1
int sum = 0, flag = 0; //flag标记是否是不符合现象
//遍历数组
for(int i=0;i<len;i++){
if((num>>i)&1){
for(int j=0;j<len;j++){
if(statements[i][j]!=2&&statements[i][j]!=(num>>j&1)){
flag = 1;
break;
}
}
sum++;
}
if(flag) break;
}
//如果该情况符合,比较出最多的好人
if(flag==0)
maxx = max(maxx, sum);
}
return maxx;
}
};