因为英文和数字很少,所以就枚举要提醒的字母和数字,验证是否可以算出来然后再更新答案。
可以推出来的有以下几种:
已知颜色,数字未知的只剩下一个
已知数字,颜色未知的只剩下一个
最后剩下一个
#include<cstdio>
#include<cstring>
using namespace std;
int n,a[6][6],k1[6],tot1,k2[6],tot2,ans=25,v[6][6];
char c[3];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",c);
a[(c[0]=='R'?1:(c[0]=='G'?2:(c[0]=='B'?3:(c[0]=='W'?4:5))))][c[1]-'0']=1;
}
for(int i=0;i<(1<<5);i++){
tot1=0;memset(k1,0,sizeof(k1));
for(int k=0;k<5;k++)if(i>>k&1)tot1++,k1[k+1]=1;
for(int j=0;j<(1<<5);j++){
tot2=0;memset(k2,0,sizeof(k2));
for(int k=0;k<5;k++)if(j>>k&1)tot2++,k2[k+1]=1;
if(tot1+tot2>=ans)continue;
memset(v,0,sizeof(v));
for(int k=1;k<=5;k++)for(int l=1;l<=5;l++)if(a[k][l]&&k1[k]&&k2[l])v[k][l]=1;
while(1){
int t=0;
for(int k=1;k<=5;k++){
if(!k1[k])continue;
int tot=0,p=0;
for(int l=1;l<=5;l++)if(a[k][l]&&!v[k][l])tot++,p=l;
if(tot==1)v[k][p]=1,t++;
}
for(int k=1;k<=5;k++){
if(!k2[k])continue;
int tot=0,p=0;
for(int l=1;l<=5;l++)if(a[l][k]&&!v[l][k])tot++,p=l;
if(tot==1)v[p][k]=1,t++;
}
if(!t)break;
}
int t=0;
for(int k=1;k<=5;k++)for(int l=1;l<=5;l++)if(a[k][l]&&!v[k][l])t++;
if(t<=1)ans=tot1+tot2;
}
}
printf("%d",ans);
return 0;
}