码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 1262 (第k字典序) Password

时间:2014-12-20 16:41:42      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

题意:

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

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

分析:

我们先统计分别在每一列均在两个矩阵出现的字母,然后从小到大排好序。

对于第一个样例来说,我们得到ACDW、BOP、GMOX、AP、GSU

则一共有4×3×4×2×3=288种密码,我们先计算这个数列的后缀积:288、72、24、6、3、1

要确定第一个字母,如果1≤k≤72,则是A;如果73≤k≤144,则是C,以此类推。

确定第二个字母是类似的,用k%72+1与24去比较。

代码实现中,字典序是从0开始的。

技术分享
 1 //#define DEBUG
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 char G[2][6][5], ans[6], select[6][5];
 6 int vis[2][26], hehe[6], cnt[5];
 7 
 8 int main()
 9 {
10     //freopen("in.txt", "r", stdin);
11 
12     int T;
13     scanf("%d", &T);
14     hehe[5] = 1;
15     while(T--)
16     {
17         memset(cnt, 0, sizeof(cnt));
18         int k;
19         scanf("%d", &k);
20         k--;    //字典序标号从0开始
21         for(int i = 0; i < 2; ++i)
22             for(int j = 0; j < 6; ++j)
23                 scanf("%s", G[i][j]);
24 
25         for(int i = 0; i < 5; ++i)
26         {
27             memset(vis, 0, sizeof(vis));
28             for(int j = 0; j < 2; ++j)
29                 for(int k = 0; k < 6; ++k)
30                     vis[j][G[j][k][i]-A] = 1;
31             for(int j = 0; j < 26; ++j)
32                 if(vis[0][j] && vis[1][j])
33                     select[i][cnt[i]++] = A + j;
34         }
35 
36         #ifdef DEBUG
37         for(int i = 0; i < 5; ++i)
38         {
39             for(int j = 0; j < select[i].size(); ++j)
40                 printf("%c", select[i][j]);
41             puts("");
42         }
43         #endif // DEBUG
44 
45         for(int i = 4; i >= 0; --i)
46             hehe[i] = cnt[i] * hehe[i+1];
47         if(k >= hehe[0])
48         {
49             puts("NO");
50             continue;
51         }
52         for(int i = 0; i < 5; ++i)
53         {
54             int m = k / hehe[i+1];
55             ans[i] = select[i][m];
56             k = k % hehe[i+1];
57         }
58         ans[5] = \0;
59 
60         printf("%s\n", ans);
61     }
62 
63     return 0;
64 }
代码君一

 

解法二:

因为密码最多有65 = 7776种,所以可以按字典序从小到大枚举。

思维难度小,写起来更快更对。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 int k, cnt;
 5 char G[2][6][5], ans[6];
 6 
 7 bool dfs(int col)
 8 {
 9     if(col == 5)
10     {
11         if(++cnt == k)
12         {
13             ans[col] = \0;
14             printf("%s\n", ans);
15             return true;
16         }
17         return false;
18     }
19 
20     bool vis[2][26];
21     memset(vis, false, sizeof(vis));
22     for(int i = 0; i < 2; ++i)
23         for(int j = 0; j < 6; ++j)
24             vis[i][G[i][j][col] - A] = 1;
25     for(int i = 0; i < 26; ++i)
26         if(vis[0][i] && vis[1][i])
27         {
28             ans[col] = i + A;
29             if(dfs(col+1)) return true;
30         }
31     return false;
32 }
33 
34 int main()
35 {
36     //freopen("in.txt", "r", stdin);
37     int T;
38     scanf("%d", &T);
39     while(T--)
40     {
41         scanf("%d", &k);
42         for(int i = 0; i < 2; ++i)
43             for(int j = 0; j < 6; ++j)
44                 scanf("%s", G[i][j]);
45 
46         cnt = 0;
47         if(!dfs(0)) puts("NO");
48     }
49 
50     return 0;
51 }
代码君二

 

UVa 1262 (第k字典序) Password

标签:

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4175508.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!