CodeForces 443C Borya and Hanabi

/*
题目链接: 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;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值