UVA 1262 - Password(暴搜/计数)
题目链接 https://cn.vjudge.net/problem/UVA-1262
【题意】
给两个6行5列的字母矩阵,找出满足如下条件的密码,密码长度为5位,密码中的每个字母在两个矩阵的对应列中均出现.比如密码的左数第二个字母必须同时在两个矩阵的第二列出现.你要找出字典序为第K小的密码(K<=7777)无解时输出”NO”
【思路】
这题本意是可以计数计算的,但数据范围小可以直接暴搜
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10;
int K,num;
char s1[N][N],s2[N][N];
vector<char> g[N];
int p[5];
bool dfs(int a,int b,int c,int d,int e){
++num;
if(num==K){
p[0]=a,p[1]=b,p[2]=c,p[3]=d,p[4]=e;
return true;
}
if(e+1<g[4].size()) return dfs(a,b,c,d,e+1);
else{
if(d+1<g[3].size()) return dfs(a,b,c,d+1,0);
else{
if(c+1<g[2].size()) return dfs(a,b,c+1,0,0);
else{
if(b+1<g[1].size()) return dfs(a,b+1,0,0,0);
else{
if(a+1<g[0].size()) return dfs(a+1,0,0,0,0);
else return false;
}
}
}
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&K);
for(int i=0;i<N;++i) g[i].clear();
for(int i=0;i<6;++i) scanf("%s",s1[i]);
for(int i=0;i<6;++i) scanf("%s",s2[i]);
for(int j=0;j<5;++j){
for(int i=0;i<6;++i){
for(int k=0;k<6;++k){
if(s1[i][j]==s2[k][j]) g[j].push_back(s1[i][j]);
}
}
}
bool ok=true;
for(int i=0;i<5;++i){
if(g[i].empty()){ok=false;break;}
sort(g[i].begin(),g[i].end());
g[i].erase(unique(g[i].begin(),g[i].end()),g[i].end());
}
if(!ok){puts("NO");continue;}
num=0;
if(dfs(0,0,0,0,0)){
for(int i=0;i<5;++i) printf("%c",g[i][p[i]]);
puts("");
}
else puts("NO");
}
return 0;
}