/*
题目链接: http://codeforces.com/contest/442/problem/A
参考: http://blog.csdn.net/codebattle/article/details/39118471
题目大意:小明有25种牌,每张有花色和数值,
现在他知道手里有哪些牌,但是不知道哪个是哪个。
旁边的人可以提示他花色,把某个花色的牌全部告诉他,或者数值,同理。
求最少提示次数,小明就能分清全部牌。
状态压缩强无敌
因为最多提示10次就能把全部牌分清
状态压缩10种提示 暴力枚举全部情况 2^10
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <sstream>
#include <map>
#include <set>
#define pi acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define debug(a) printf("---%d---\n", a)
#define mem0(a) memset(a, 0, sizeof(a))
#define memi(a) memset(a, inf, sizeof(a))
#define mem1(a) memset(a, -1, sizeof(a))
#define input1(a) scanf("%d", &a)
#define input2(a,b) scanf("%d %d", &a, &b)
#define input3(a,b,c) scanf("%d %d %d", &a, &b, &c)
using namespace std;
typedef pair<int, int> P;
const double eps = 1e-10;
const int maxn = 1e6 + 5;
const int N = 1e4 + 5;
const int mod = 1e8;
char s[5];
int mp[11][11], cnt[11];
int change(char ch)
{
if (ch == 'R') return 5;
if (ch == 'G') return 6;
if (ch == 'B') return 7;
if (ch == 'Y') return 8;
if (ch == 'W') return 9;
}
int main(void)
{
// freopen("in.txt","r", stdin);
int n;
cin >> n;
memset(mp, 0, sizeof(mp));
for (int i = 1; i <= n; i++){
cin >> s;
int x = s[1] - '1';
int y = change(s[0]);
mp[x][y] = 1;
}
int ans = 10; // ans最多为10 提示10次就全clear了
for (int S = 0; S < (1<<10); S++){ // 将10个提示状态压缩
int num = 0, flag = 1, cnt_ = 0;
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < 10; i++)
if (S & (1 << i)) num++; //num为当前状态S所用到的提示个数
if (num > ans) continue;
for (int i = 0; i < 5; i++){ // 数字与字母组合
for (int j = 2; j < 10; j++){
if (mp[i][j]){ // 有这个组合
if ((S & (1<<i)) && (S & (1<<j)))
continue;
else if (S & (1<<i)){
cnt[i]++; // 如果cnt[i]超过1 说明i是不能被区分的
if (cnt[i] > 1) flag = 0; // 即当前状态S不能将牌分清
}
else if (S & (1<<j)){
cnt[j]++; // 同cnt[i]
if (cnt[j] > 1) flag = 0;
}
else {
cnt_++; // 如果只有1个牌的两个属性都没被提醒 是可以的
if (cnt_ > 1) flag = 0; // 但是超过1个就不行了
}
}
}
}
if (flag) ans = min(ans, num); //如果当前状态S符合 更新ans
}
cout << ans << endl;
return 0;
}
CodeForces 443C Borya and Hanabi
最新推荐文章于 2019-02-26 12:01:00 发布