• 【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

  • 相关阅读:
    3. 无重复字符的最长子串
    字节跳动 最小栈
    排序
    线程的优先级
    线程的操作方法
    线程的生命周期
    实现线程的方式:Thread类重写run();Runnable类重写run();Callable类重写call();实现线程的方式
    Java thread run() start() 是干什么的以及区别
    Java thread 多线程
    助教工作学期总结
  • 原文地址:https://www.cnblogs.com/YJinpeng/p/5907200.html
Copyright © 2020-2023  润新知