USACO 5.5.3 Two Five

题目大意:

一种语言以5*5的矩阵表示,分别填入‘A’-‘Y’,要求每一行、每一列都递增。
为方便,将所有合法矩阵按字典序大小编号。
要求实现矩阵与编号的转换。
 
简单题解:
刚看到这题的时候,毫无头绪。
看了NOCOW上的题解才恍然大悟。
这题卡了我4天。
蛋疼的是,第二天的时候我已经改对了,但是将输出与样例比对时坑爹了....
 
矩阵转编号:
如矩阵ACEGI......
只需求出以AB、ACD、ACEF、ACEFH......开头的矩阵的数目之和再加1即可。
编号转矩阵:
顺次枚举每一位,若当前方案开头的矩阵数目小于n则减去,否则即可确定当前位。
 
如何求以固定串开头的矩阵数目呢?
记忆化搜索!
令f[a][b][c][d][e]表示各行分别放入了a,b,c,d,e个字符的方案数。
则合法状态中,必然五参数不严格递减。
从小往大枚举每一字符,选择放到哪一行中,且必然放在该行接下来的一格中。
 
我的代码:
 1 /*
 2 ID:t-x.h1
 3 LANG:C++
 4 TASK:twofive
 5 */
 6 #include<cstdio>
 7 #include<cstdlib>
 8 #include<cstring>
 9 #define max(x,y) ((x)>(y)?(x):(y))
10 #define ok(x) (!t[x] || t[x]==deep+'A')
11 FILE *fi=fopen("twofive.in","r"),*fo=fopen("twofive.out","w");
12 const int N=25;
13 char c,t[N+9];
14 int f[6][6][6][6][6];
15 bool mark[128];
16 int dfs(int a,int b,int c,int d,int e,int deep)
17 {
18         if(deep==N)
19                 return 1;
20         int &now=f[a][b][c][d][e];
21         if(now)
22                 return now;
23         if(a<5 && ok(a))
24                 now+=dfs(a+1,b,c,d,e,deep+1);
25         if(b<a && ok(b+5))
26                 now+=dfs(a,b+1,c,d,e,deep+1);
27         if(c<b && ok(c+10))
28                 now+=dfs(a,b,c+1,d,e,deep+1);
29         if(d<c && ok(d+15))
30                 now+=dfs(a,b,c,d+1,e,deep+1);
31         if(e<d && ok(e+20))
32                 now+=dfs(a,b,c,d,e+1,deep+1);
33         return now;
34 }
35 int main()
36 {
37         int i=fgetc(fi),ans=0;
38         if(i=='N')
39         {
40                 int n,tmp;
41                 fscanf(fi,"%d",&n);
42                 for(i=0;i<N;++i)
43                         for(t[i]='A';memset(f,0,sizeof(f)),(tmp=dfs(0,0,0,0,0,0))<n;++t[i])
44                                 n-=tmp;
45                 fprintf(fo,"%s\n",t);
46         }
47         else
48         {
49                 char s[N+9];
50                 fscanf(fi,"%s",s);
51                 for(i=0;i<N;++i)
52                         for(t[i]='A';t[i]<s[i];++t[i])
53                         {
54                                 memset(f,0,sizeof(f));
55                                 ans+=dfs(0,0,0,0,0,0);
56                         }
57                 fprintf(fo,"%d\n",ans+1);
58         } 
59         fclose(fi);
60         fclose(fo);
61         return 0;
62 }

 

posted @ 2012-08-18 13:02  凌云七风  阅读(816)  评论(0编辑  收藏  举报