题意:给两个6行5列的字母矩阵,找到密码:密码中的每个字母都在两个矩阵中的对应列出现。在这样的密码中找到字典序第k大的密码。
我的思路:先找出两个矩阵相同列中相同的元素,并将它们排序,在验证一定有解后递归打印字典序第k大的密码就行了。
具体实现见代码:
#include<bits/stdc++.h>
using namespace std;
int T,k;
char grap1[6][6],grap2[6][6],same[5][7];
int cnt[6],vis[26],k1;
void get_same(){ ///找出两个矩阵中相同列的相同字母
memset(cnt,0,sizeof(cnt)); ///记录每一列中相同字母的个数
for(int i=0;i<5;i++){
memset(vis,0,sizeof(vis)); ///防止生成的same的一列中出现相同字母
for(int j=0;j<6;j++){
char a=grap1[j][i];
for(int k=0;k<6;k++) if(!vis[a-'A']){
if(a==grap2[k][i]){
vis[a-'A']=1;
same[i][cnt[i]++]=grap1[j][i];
}
}
}
}
for(int i=0;i<5;i++) sort(same[i],same[i]+cnt[i]);
}
bool confirm(){ ///确认是否有解
int max_k=1;
for(int i=0;i<5;i++) max_k*=cnt[i];
return max_k>=k?1:0;
}
void permutation(char* s,int n){ ///DFS求字典序第k大的密码
if(n==5&&k==++k1){
printf("%s\n",s);
return;
}
for(int i=0;i<cnt[n];i++){
s[n]=same[n][i];
permutation(s,n+1);
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&k);
for(int i=0;i<6;i++) scanf("%s",grap1[i]);
for(int i=0;i<6;i++) scanf("%s",grap2[i]);
get_same();
char s[6];
k1=0;
if(confirm()) permutation(s,0);
else printf("NO\n");
}
return 0;
}