题意:
牌有5个花色和5个数值,共5*5=25种牌型。现在小A已知他有哪些牌以及各种牌有多少张,但是不知道
这些牌摆放的顺序。现在他可以要求提示某个花色或数值,这样他可以知道哪些牌是这个花型或者哪些
牌是这个数值。问他最少需要几次提示才能确定所有牌的位置。
算法:
由于花色和数值都只有5,那么询问的总状态数为(1<<11)-1。
枚举每个状态,判断是否能确定所有牌的位置。在能确定的合法状态中找最小的询问次数,即状态压缩的
那个数中1的个数。
考虑哪种状态合法不好判断,思考哪种状态不合法比较容易。
以下两种情况出现任何一种都不合法:
1.某种牌的两个端点都没询问,而且不止一次(如果只是一次的话,是可以的,因为主人知道所有的牌,这张牌放到最后即可)。
2.某种牌只访问了一个端点,但是这个端点又不止被访问一次(这样的话就肯定无法确定是哪张牌)
#include<cstdio>
#include<iostream>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
int mp[12][12],num[12],ans;
char a[]={'R','G','B','Y','W'};
int change(char c)
{
for(int i=0;i<5;i++)
{
if(c==a[i])
return i;
}
}
int bitcount(int x)
{
return x==0?x:bitcount(x>>1)+(x&1);
}
bool judge(int sta)
{
int sum = 0;
memset(num,0,sizeof(num));
for(int i=1;i<=5;i++)
{
for(int j=6;j<=10;j++)
{
if(!mp[i][j]) continue;
if(sta&(1<<(i-1)) && !(sta&(1<<(j-1))))
num[i]++;
if(!(sta&(1<<(i-1))) && sta&(1<<(j-1)))
num[j]++;
if(!(sta&(1<<(i-1))) && !(sta&(1<<(j-1))))
sum++;
}
}
if(sum>1) return false;
for(int i=1;i<=10;i++)
{
if(num[i]>1)
return false;
}
return true;
}
void solve()
{
ans = 100;
for(int x=0;x<(1<<11);x++)
{
if(judge(x))
ans = min(ans,bitcount(x));
}
printf("%d\n",ans);
}
int main()
{
char s[5];
int n;
while(scanf("%d",&n)!=EOF)
{
memset(mp,0,sizeof(mp));
for(int e=0;e<n;e++)
{
scanf("%s",s);
int i=change(s[0])+1;
int j=s[1]-'0'+5;
mp[i][j] = 1;
}
solve();
}
return 0;
}