T105008 answer(hash)
满分做法:
对于有全对的时候,直接枚举每个人的答案为最终答案,判断和他完全相反的字符串是否为p个即可。
对于没有全对但有全错的时候,枚举每个答案为错误答案,并判断和他完全相反的字符串是否有即可。
对于p,q都是0时,先假定全是N(保证字典序最小),然后判定有无,无的话直接输出;有,就二进制枚举后面Y,N的顺序暴力替换,在判定即可。
#include<queue> #include<cstring> #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<map> using namespace std; typedef long long ll; const int maxm=30007; map<string,int> num,flag; string s[maxm]; int n,m,p,q; string ans; int main() { //freopen("answer.in","r",stdin); //freopen("answer.out","w",stdout); scanf("%d%d%d%d",&n,&m,&p,&q); for(int i=1;i<=n;i++) { cin>>s[i]; num[s[i]]++; } if(p==0&&q==0) { string fan=""; string dui=""; for(int i=1;i<=m;i++) { fan+='N'; dui+='Y'; } if(!num[fan]&&!num[dui]) { cout<<fan; return 0; } else { for(int i=1;i<=n+1;i++) { string jia=""; string jj=""; int len; for(int j=19;j>=1;j--) { if((1<<(j-1))&i) { len=j; break; } } for(int j=len;j>=1;j--) { if((1<<(j-1))&i) { jia+='Y'; jj+='N'; } else jia+='N',jj+='Y'; } string ans1=fan.substr(0,m-len)+jia; string ans2=dui.substr(0,m-len)+jj; if(!num[ans1]&&!num[ans2]) { cout<<ans1; return 0; } } } return 0; } if(p==0&&q) { for(int i=1;i<=n;i++) { if(flag[s[i]]==0&&num[s[i]]==q) { string fan=""; for(int j=0;j<m;j++) { if(s[i][j]=='Y') fan+='N'; else fan+='Y'; } if(ans[0]!='Y'&&ans[0]!='N') ans=fan; else { for(int j=0;j<m;j++) { if(ans[j]<fan[j]) break; if(ans[j]==fan[j]) continue; else { ans=fan; break; } } } flag[s[i]]=1; } } } else { for(int i=1;i<=n;i++) { if(flag[s[i]]==0&&num[s[i]]==p) { string fan=""; for(int j=0;j<m;j++) { if(s[i][j]=='Y') fan+='N'; else fan+='Y'; } if(num[fan]!=q) continue; if(ans[0]!='Y'&&ans[0]!='N') ans=s[i]; else { for(int j=0;j<m;j++) { if(ans[j]<s[i][j]) break; if(ans[j]==s[i][j]) continue; else { ans=s[i]; break; } } } flag[s[i]]=1; } } } if(ans[0]!='Y'&&ans[0]!='N') printf("-1\n"); else { for(int j=0;j<m;j++) cout<<ans[j]; } return 0; }