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;
}
posted @ 2018-08-22 10:45  不想吃WA的咸鱼  阅读(118)  评论(0编辑  收藏  举报