USACO 5.5 Twofive

Twofive
IOI 2001

In order to teach her young calvess the order of the letters in the alphabet, Bessie has come up with a game to play with them. The calves are given a 5 x 5 grid on which they can put the letters 'A'-'Y', but the one rule is that all the letters going across the columns and down the rows must be in the order they appear in the alphabet.

There are a huge number of possible grids, so Bessie decides that they will be named by the string of letters that is given by reading across each row, going down the rows. For example, the grid: 

 
     A B C D E
     F G H I J
     K L M N O
     P Q R S T 
     U V W X Y


would have the name ABCDEFGHIJKLMNOPQRSTUVWXY, which is coincidentally the first possible grid when the entire set of grids is ordered alphabetically. The second grid that meets this requirement is ABCDEFGHIJKLMNOPQRSUTVWXY, which is formed by switching the 'T' and 'U' in the above grid.

Help the calves gain bragging rights. Given a number, M, find which string is Mth in the list of all possible grids when they are sorted alphabetically, and, given a string of letters, find out what number the corresponding grid is in the list of all possible grids.

PROGRAM NAME: twofive

INPUT FORMAT

The first input line contains one of two letters, either an 'N' or a 'W'.

If the first input line contains an 'N', the second line will contain an integer, M, that corresponds to the number of a valid grid. If the first line contains a 'W', the second line will contain a string of 25 letters, which represents a valid grid.

OUTPUT FORMAT

If the input contained the number of a valid grid (first line 'N'), the output should contain a string of 25 letters on a line, which corresponds to the Mth grid in the sorted list of all possible grids.

If the input contained a string of letters indicating a grid (first line 'W'), the output should contain a single integer on a line, which corresponds to the number of the given grid in the list of all possible grids.

SAMPLE INPUT #1 (file twofive.in)

N
2

SAMPLE OUTPUT #1 (file twofive.out)

ABCDEFGHIJKLMNOPQRSUTVWXY

SAMPLE INPUT #2 (file twofive.in)

W
ABCDEFGHIJKLMNOPQRSUTVWXY

SAMPLE OUTPUT #2 (file twofive.out)

2

 

——————————————————————————————————题解

越刷神题越多……

这道题的思路和介个差不多虽然这道没有做出来

一开始的思路就是赤裸裸的暴力然后map,结果跑不动qwq

然后我要开始写一份详细的解题报告了

如果是编码转单词:

初始计数器s=0,编码为d

计算AB开头所有的单词x,如果s+x>=d,那么我们可以发现AB开头的所有单词囊括了所有1-d的单词,所以第二位就是B

如果s+x<d,那么1-d中包含了AB开头所有单词,那么我们继续枚举下一位,直到满足s+x>=d

由此可以计算出这个单词

如果是单词转编码:

初始计数器s=0

假如一个串AFKPUBGLQVCHMRWDINSXEJOTY

这个单词之前一定有AB,AC,AD,AE开头的所有单词,用s累加上他们的和

然后处理AFB开头的所有单词(处理出来会是0)AFC……AFJ开头的所有单词和,以下位同理

最后s+1就是我们想要的解

 

那么我们如何计算一个固定前缀开头所有单词的和,用记忆化搜索f[a][b][c][d][e]表示第一行有a个字符,第二行有b个字符,第三行有c个字符,第四行有d个字符,第五行有e个字符,其中这些字符是前a+b+c+d+e个字符,且a->e递减,我们再记一个ans序列是我们固定好的前缀,如果搜索到该位置要往里面填一个字母,这个位置没有字母或者这个位置的字母正好是我们ans里记录的,我们就填,否则跳过

这个记忆化搜索的边界条件是搜满了之后填1

据说用5位六进制数可以让程序变得美观然而我没有

  1 /*
  2 ID: ivorysi
  3 LANG: C++
  4 PROG: twofive
  5 */
  6 #include <iostream>
  7 #include <cstdio>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <set>
 12 #include <vector>
 13 #include <string.h>
 14 #include <cmath>
 15 #include <stack>
 16 #include <map>
 17 #define siji(i,x,y) for(int i=(x);i<=(y);++i)
 18 #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
 19 #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
 20 #define sigongzi(j,x,y) for(int j=(x);j>(y);--j)
 21 #define inf 0x5f5f5f5f
 22 #define ivorysi
 23 #define mo 97797977
 24 #define hash 974711
 25 #define base 47
 26 #define pss pair<string,string>
 27 #define MAXN 5000
 28 #define fi first
 29 #define se second
 30 #define pii pair<int,int>
 31 #define esp 1e-8
 32 typedef long long ll;
 33 using namespace std;
 34 ll f[8][8][8][8][8],d,s;
 35 int used[30];
 36 char ans[30],str[30];
 37 void init() {
 38     siji(i,0,5) {
 39         siji(j,0,5) {
 40             siji(k,0,5) {
 41                 siji(z,0,5) {
 42                     siji(o,0,5) {
 43                         f[i][j][k][z][o]=-1;
 44                     }
 45                 }
 46             }
 47         }
 48     }
 49 }
 50 int dfs(int a1,int a2,int a3,int a4,int a5,char t) {
 51     if(f[a1][a2][a3][a4][a5]!=-1)return f[a1][a2][a3][a4][a5];
 52     if(t>'Y') return f[a1][a2][a3][a4][a5]=1;
 53     f[a1][a2][a3][a4][a5]=0;
 54     if(a1+1<=5 && (ans[a1+1]==t || ans[a1+1]==0)) 
 55         f[a1][a2][a3][a4][a5]+=dfs(a1+1,a2,a3,a4,a5,t+1);
 56     if(a2+1<=a1 && (ans[a2+6]==t || ans[a2+6]==0)) 
 57         f[a1][a2][a3][a4][a5]+=dfs(a1,a2+1,a3,a4,a5,t+1);
 58     if(a3+1<=a2 && (ans[a3+11]==t || ans[a3+11]==0)) 
 59         f[a1][a2][a3][a4][a5]+=dfs(a1,a2,a3+1,a4,a5,t+1);
 60     if(a4+1<=a3 && (ans[a4+16]==t || ans[a4+16]==0)) 
 61         f[a1][a2][a3][a4][a5]+=dfs(a1,a2,a3,a4+1,a5,t+1);
 62     if(a5+1<=a4 && (ans[a5+21]==t || ans[a5+21]==0)) 
 63         f[a1][a2][a3][a4][a5]+=dfs(a1,a2,a3,a4,a5+1,t+1);
 64     return f[a1][a2][a3][a4][a5];
 65 }
 66 void solve() {
 67     scanf("%s",str+1);
 68     if(str[1]=='N') {
 69         scanf("%d",&d);
 70         ans[1]='A';
 71         siji(i,2,25) {
 72             siji(j,1,24) {
 73                 if(!used[j]) {
 74                     ans[i]='A'+j;
 75                     used[j]=1;
 76                     init();
 77                     int x=dfs(0,0,0,0,0,'A');
 78                     if(s+x>=d) break;
 79                     else {used[j]=0;s+=x;}
 80                 }
 81             }
 82         }
 83         printf("%s\n",ans+1);
 84     }
 85     else {
 86         scanf("%s",str+1);
 87         ans[1]='A';
 88         //@used[1]=1这里多了一句这句话,实际上used是记录'A'+j被用过,如果这样我们就无法填B了
 89         siji(i,2,25) {
 90             xiaosiji(j,1,str[i]-'A'){
 91                 if(!used[j]) {
 92                     ans[i]='A'+j;
 93                     init();
 94                     s+=dfs(0,0,0,0,0,'A');
 95                 }
 96             }
 97             ans[i]=str[i];
 98             used[str[i]-'A']=1;
 99         }
100         printf("%d\n",s+1);
101     }
102 }
103 int main(int argc, char const *argv[])
104 {
105 #ifdef ivorysi
106     freopen("twofive.in","r",stdin);
107     freopen("twofive.out","w",stdout);
108 #else
109     freopen("f1.in","r",stdin);
110 #endif
111     solve();
112     return 0;
113 }

 

posted @ 2017-02-21 20:37  sigongzi  阅读(726)  评论(0编辑  收藏  举报