暴力枚举 (细节处理)

题意:

给出两个6行5列的字母矩阵,一个密码满足:密码的第i个字母在两个字母矩阵的第i列均出现。

然后找出字典序为k的密码,如果不存在输出NO

思路分析 :

暴力枚举就可以,但是有两个细节,每一列的字母必须是同时出现在两个表中的,并且要保证相同的字母出现多次均按照一次计算

代码示例 :

#define ll long long
const ll maxn = 1e6+5;
const ll mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;

ll n;
char a[10][10], b[10][10];
map<char, ll>mp;
vector<char>ve[10];
ll num[10];

void init(){
    for(ll i = 1; i <= 5; i++) ve[i].clear();
    memset(num, 0, sizeof(num));
    
    for(ll i = 1; i <= 5; i++){
        mp.clear();
        for(ll j = 1; j <= 6; j++){ 
            mp[a[j][i]]++;
        }
        for(ll j = 1; j <= 6; j++){
            if (mp[b[j][i]] > 0) {
                ve[i].push_back(b[j][i]);
                mp[b[j][i]] = 0;
                num[i]++;
            }
        }
    }
    for(ll i = 1; i <= 5; i++) sort(ve[i].begin(), ve[i].end());    
}

void fun(ll k, ll x){ 
    if (k == 6) return;
    ll s = 1;
    for(ll i = k+1; i <= 5; i++){
        s *= num[i];
    }
    ll sum = s;    
    for(ll i = 0; i < num[k]; i++){
        if (sum >= x) {
            printf("%c", ve[k][i]);
            fun(k+1, x-i*s);
            return;
        }
        sum += s;
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    ll t;
    
    cin >> t;
    while(t--){
        scanf("%lld", &n); 
        for(ll i = 1; i <= 6; i++){
            scanf("%s", a[i]+1);
        }            
        for(ll i = 1; i <= 6; i++){
            scanf("%s", b[i]+1);
        }
        init(); 
        ll sum = 1;
        for(ll i = 1; i <= 5; i++) sum *= num[i];
        if (sum < n) {printf("NO\n"); continue;}
        fun(1, n);
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-04-24 17:54  楼主好菜啊  阅读(152)  评论(0编辑  收藏  举报