Codevs1322 单词矩阵

3 篇文章 0 订阅
2 篇文章 0 订阅

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

// <twofive.cpp> - Mon Sep 19 08:11:51 2016
// This file is made by YJinpeng,created by XuYike's black technology automatically.
// Copyright (C) 2016 ChangJun High School, Inc.
// I don't know what this program is.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#define MOD 1000000007
#define INF 1e9
using namespace std;
typedef long long LL;
const int MAXN=6;
const int MAXM=36;
inline int max(int &x,int &y) {return x>y?x:y;}
inline int min(int &x,int &y) {return x<y?x:y;}
inline int gi() {
    register int w=0,q=0;register char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')q=1,ch=getchar();
    while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
    return q?-w:w;
}
char s[MAXM];int ans[MAXM];
int f[MAXN][MAXN][MAXN][MAXN][MAXN];
inline bool check(int x,int c){return ans[x]?ans[x]==c:1;}
inline int src(int a,int b,int c,int d,int e,int tot){
    if(tot==25)return 1;
    int &tmp=f[a][b][c][d][e];
    if(tmp)return tmp;
    if(a<5&&check(a,tot+1))tmp+=src(a+1,b,c,d,e,tot+1);
    if(b<a&&check(b+5,tot+1))tmp+=src(a,b+1,c,d,e,tot+1); 
    if(c<b&&check(c+10,tot+1))tmp+=src(a,b,c+1,d,e,tot+1);
    if(d<c&&check(d+15,tot+1))tmp+=src(a,b,c,d+1,e,tot+1);
    if(e<d&&check(e+20,tot+1))tmp+=src(a,b,c,d,e+1,tot+1);
    return tmp;
}
int main()
{
    freopen("twofive.in","r",stdin);
    freopen("twofive.out","w",stdout);
    char type=getchar();int n=0;
    if(type=='W'){
        scanf("%s",s);
        for(int i=0;i<25;i++)
            for(ans[i]=1;ans[i]<s[i]-'A'+1;ans[i]++){
                memset(f,0,sizeof(f));
                n+=src(0,0,0,0,0,0);
            }
        printf("%d",n+1);
    }else{
        n=gi();
        for(int i=0;i<25;i++)
            for(ans[i]=1;ans[i]<=26;ans[i]++){
                memset(f,0,sizeof(f));
                int now=src(0,0,0,0,0,0);
                if(now>=n)break;n-=now;
            }
        for(int i=0;i<25;i++)putchar(int(ans[i]+'A'-1));
    }
    return 0;
}

小优化-s

// <twofive.cpp> - Mon Sep 19 08:11:51 2016
// This file is made by YJinpeng,created by XuYike's black technology automatically.
// Copyright (C) 2016 ChangJun High School, Inc.
// I don't know what this program is.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#define MOD 1000000007
#define INF 1e9
using namespace std;
typedef long long LL;
const int MAXN=6;
const int MAXM=36;
inline int max(int &x,int &y) {return x>y?x:y;}
inline int min(int &x,int &y) {return x<y?x:y;}
inline int gi() {
    register int w=0,q=0;register char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')q=1,ch=getchar();
    while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
    return q?-w:w;
}
char s[MAXM];int ans[MAXM],used[MAXM];
int f[MAXN][MAXN][MAXN][MAXN][MAXN];
inline bool check(int x,int c){return ans[x]?ans[x]==c:1;}
inline int src(int a,int b,int c,int d,int e,int tot){
    if(tot==25)return 1;
    int &tmp=f[a][b][c][d][e];
    if(tmp)return tmp;
    if(a<5&&check(a,tot+1))tmp+=src(a+1,b,c,d,e,tot+1);
    if(b<a&&check(b+5,tot+1))tmp+=src(a,b+1,c,d,e,tot+1); 
    if(c<b&&check(c+10,tot+1))tmp+=src(a,b,c+1,d,e,tot+1);
    if(d<c&&check(d+15,tot+1))tmp+=src(a,b,c,d+1,e,tot+1);
    if(e<d&&check(e+20,tot+1))tmp+=src(a,b,c,d,e+1,tot+1);
    return tmp;
}
int main()
{
    freopen("twofive.in","r",stdin);
    freopen("twofive.out","w",stdout);
    char type=getchar();int n=0;
    memset(used,false,sizeof(used));
    if(type=='W'){
        scanf("%s",s);
        for(int i=0;i<25;i++){
            for(ans[i]=1;ans[i]<s[i]-'A'+1;ans[i]++){
                if(used[ans[i]])continue;
                memset(f,0,sizeof(f));
                n+=src(0,0,0,0,0,0);
            }
            used[ans[i]]=1;
        }
        printf("%d",n+1);
    }else{
        n=gi();
        for(int i=0;i<25;i++){
            for(ans[i]=1;ans[i]<=26;ans[i]++){
                if(used[ans[i]])continue;
                memset(f,0,sizeof(f));
                int now=src(0,0,0,0,0,0);
                if(now>=n)break;n-=now;
            }
            used[ans[i]]=1;
        }
        for(int i=0;i<25;i++)putchar(int(ans[i]+'A'-1));
    }
    return 0;
}

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值