【Codevs1322】单词矩阵

Position:


List

Description

对于包含字母A到Y各一次的单词S,将其从上到下从左到右写在一个5*5的矩阵中,如单词ADJPTBEKQUCGLRVFINSWHMOXY写出来如下:
A D J P T
B E K Q U
C G L R V
F I N S W
H M O X Y
若该矩阵满足每一行每一列的字母都是字典序递增的则称S为优美的,如上述单词就是优美的,而ADJPTBEGQUCKLRVFINSWHMOXY则不是(第二列不满足要求)。
Your Task
将所有优美的单词按字典序列出,从小到大编号1,2,……
请你完成以下两种任务:
1. 给定一个优美的单词,求其编号。
2. 给定一个编号,求对应的优美的单词。

Input

第一行一个字母,W表示任务1,N表示任务2
若是任务1,第二行是一个优美的单词,否则第二行是一个正整数,表示某个优美的单词的编号,保证该数不超过优美的单词的总数

Output

一行,若是任务1,输出对应编号,否则输出对应的优美的单词

Sample Input


  1. W
    ABCDEFGHIJKLMNOPQRSUTVWXY

  2. N
    20

Sample Output


  1. 2

  2. ABCDEFGHIJKLMNOPQSUWRTVXY

HINT

Solution

普通搜索显然TLE(枚举每一位填什么字母O(26!))
注意条件每一行每一列的字母都是字典序递增→每个字母必须小于右下方所有的字母
考虑从A到Z依次填入矩阵0~24中,记忆化搜索f[a][b][c][d][e]记录当前状态后继方案数,满足a>b>c>d>e,并且当前已经填入的数要是原样,src(a,b,c,d,e,tot)tot记录要填入哪个字母。
对于第一个任务,求编号,那么每个位置可以填1~s[i]-‘A’+1,统计之前的方案数,最终方案数加上自己即可+1。
对于第二个任务,求方案,那么每个位置从’A’开始填,知道>n,最终求出的即为结果。
码题解的时候发现如果用过的字母就不要用了,加上优化发现快了不少。

Code

 1 // <twofive.cpp> - Mon Sep 19 08:11:51 2016
 2 // This file is made by YJinpeng,created by XuYike's black technology automatically.
 3 // Copyright (C) 2016 ChangJun High School, Inc.
 4 // I don't know what this program is.
 5 
 6 #include <iostream>
 7 #include <vector>
 8 #include <algorithm>
 9 #include <cstring>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cmath>
13 #define MOD 1000000007
14 #define INF 1e9
15 using namespace std;
16 typedef long long LL;
17 const int MAXN=6;
18 const int MAXM=36;
19 inline int max(int &x,int &y) {return x>y?x:y;}
20 inline int min(int &x,int &y) {return x<y?x:y;}
21 inline int gi() {
22     register int w=0,q=0;register char ch=getchar();
23     while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
24     if(ch=='-')q=1,ch=getchar();
25     while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
26     return q?-w:w;
27 }
28 char s[MAXM];int ans[MAXM];
29 int f[MAXN][MAXN][MAXN][MAXN][MAXN];
30 inline bool check(int x,int c){return ans[x]?ans[x]==c:1;}
31 inline int src(int a,int b,int c,int d,int e,int tot){
32     if(tot==25)return 1;
33     int &tmp=f[a][b][c][d][e];
34     if(tmp)return tmp;
35     if(a<5&&check(a,tot+1))tmp+=src(a+1,b,c,d,e,tot+1);
36     if(b<a&&check(b+5,tot+1))tmp+=src(a,b+1,c,d,e,tot+1); 
37     if(c<b&&check(c+10,tot+1))tmp+=src(a,b,c+1,d,e,tot+1);
38     if(d<c&&check(d+15,tot+1))tmp+=src(a,b,c,d+1,e,tot+1);
39     if(e<d&&check(e+20,tot+1))tmp+=src(a,b,c,d,e+1,tot+1);
40     return tmp;
41 }
42 int main()
43 {
44     freopen("twofive.in","r",stdin);
45     freopen("twofive.out","w",stdout);
46     char type=getchar();int n=0;
47     if(type=='W'){
48         scanf("%s",s);
49         for(int i=0;i<25;i++)
50             for(ans[i]=1;ans[i]<s[i]-'A'+1;ans[i]++){
51                 memset(f,0,sizeof(f));
52                 n+=src(0,0,0,0,0,0);
53             }
54         printf("%d",n+1);
55     }else{
56         n=gi();
57         for(int i=0;i<25;i++)
58             for(ans[i]=1;ans[i]<=26;ans[i]++){
59                 memset(f,0,sizeof(f));
60                 int now=src(0,0,0,0,0,0);
61                 if(now>=n)break;n-=now;
62             }
63         for(int i=0;i<25;i++)putchar(int(ans[i]+'A'-1));
64     }
65     return 0;
66 }
View Code

小优化-s

 1 // <twofive.cpp> - Mon Sep 19 08:11:51 2016
 2 // This file is made by YJinpeng,created by XuYike's black technology automatically.
 3 // Copyright (C) 2016 ChangJun High School, Inc.
 4 // I don't know what this program is.
 5 
 6 #include <iostream>
 7 #include <vector>
 8 #include <algorithm>
 9 #include <cstring>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cmath>
13 #define MOD 1000000007
14 #define INF 1e9
15 using namespace std;
16 typedef long long LL;
17 const int MAXN=6;
18 const int MAXM=36;
19 inline int max(int &x,int &y) {return x>y?x:y;}
20 inline int min(int &x,int &y) {return x<y?x:y;}
21 inline int gi() {
22     register int w=0,q=0;register char ch=getchar();
23     while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
24     if(ch=='-')q=1,ch=getchar();
25     while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
26     return q?-w:w;
27 }
28 char s[MAXM];int ans[MAXM],used[MAXM];
29 int f[MAXN][MAXN][MAXN][MAXN][MAXN];
30 inline bool check(int x,int c){return ans[x]?ans[x]==c:1;}
31 inline int src(int a,int b,int c,int d,int e,int tot){
32     if(tot==25)return 1;
33     int &tmp=f[a][b][c][d][e];
34     if(tmp)return tmp;
35     if(a<5&&check(a,tot+1))tmp+=src(a+1,b,c,d,e,tot+1);
36     if(b<a&&check(b+5,tot+1))tmp+=src(a,b+1,c,d,e,tot+1); 
37     if(c<b&&check(c+10,tot+1))tmp+=src(a,b,c+1,d,e,tot+1);
38     if(d<c&&check(d+15,tot+1))tmp+=src(a,b,c,d+1,e,tot+1);
39     if(e<d&&check(e+20,tot+1))tmp+=src(a,b,c,d,e+1,tot+1);
40     return tmp;
41 }
42 int main()
43 {
44     freopen("twofive.in","r",stdin);
45     freopen("twofive.out","w",stdout);
46     char type=getchar();int n=0;
47     memset(used,false,sizeof(used));
48     if(type=='W'){
49         scanf("%s",s);
50         for(int i=0;i<25;i++){
51             for(ans[i]=1;ans[i]<s[i]-'A'+1;ans[i]++){
52                 if(used[ans[i]])continue;
53                 memset(f,0,sizeof(f));
54                 n+=src(0,0,0,0,0,0);
55             }
56             used[ans[i]]=1;
57         }
58         printf("%d",n+1);
59     }else{
60         n=gi();
61         for(int i=0;i<25;i++){
62             for(ans[i]=1;ans[i]<=26;ans[i]++){
63                 if(used[ans[i]])continue;
64                 memset(f,0,sizeof(f));
65                 int now=src(0,0,0,0,0,0);
66                 if(now>=n)break;n-=now;
67             }
68             used[ans[i]]=1;
69         }
70         for(int i=0;i<25;i++)putchar(int(ans[i]+'A'-1));
71     }
72     return 0;
73 }
View Code

这里不得不再提起常数优化,算法优化,小优化→大分数。这点意识真的要有,说不准快了0.01s你就多过了10分,说不准多十分你就保送,进队,金牌,一等奖,降分…… 

来看下效果:
o1
之后
o2

 

转载于:https://www.cnblogs.com/YJinpeng/p/5907200.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值