满分做法:
对于有全对的时候,直接枚举每个人的答案为最终答案,判断和他完全相反的字符串是否为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
");
else
{
for(int j=0;j<m;j++)
cout<<ans[j];
}
return 0;
}