刚看时有点蒙,看了一会儿还是不知道咋做。于是看了题解,刚看到记忆化搜索就恍然大悟。
其实也挺好想的,f[a][b][c][d][e]表示每一行填了几个数后剩下格子的填法。然后就可以推出a……或ab……等的个数。
挺短的代码:
#include<bits/stdc++.h>
using namespace std;
int f[6][6][6][6][6];
char t[30],s[30];
inline int dfs(int a,int b,int c,int d,int e,int s){
if(s==25) return 1;
int &x=f[a][b][c][d][e];
if(x>0) return x;
if(a<5&&(!t[a]||t[a]==s+'A')) x+=dfs(a+1,b,c,d,e,s+1);
if(b<a&&(!t[b+5]||t[b+5]==s+'A')) x+=dfs(a,b+1,c,d,e,s+1);
if(c<b&&(!t[c+10]||t[c+10]==s+'A')) x+=dfs(a,b,c+1,d,e,s+1);
if(d<c&&(!t[d+15]||t[d+15]==s+'A')) x+=dfs(a,b,c,d+1,e,s+1);
if(e<d&&(!t[e+20]||t[e+20]==s+'A')) x+=dfs(a,b,c,d,e+1,s+1);
return x;
}
int main()
{
freopen("twofive.in","r",stdin);
freopen("twofive.out","w",stdout);
char c;scanf("%c",&c);
if(c=='N'){
int n,x;scanf("%d",&n);
for(int i=0;i<25;++i)
for(t[i]='A';memset(f,0,sizeof(f)),(x=dfs(0,0,0,0,0,0))<n;++t[i])
n-=x;
printf("%s\n",t);
}
else{
scanf("%s",s);
int ans=0;
for(int i=0;i<25;++i)
for(t[i]='A';t[i]<s[i];++t[i]){
memset(f,0,sizeof(f));
ans+=dfs(0,0,0,0,0,0);
}
printf("%d\n",ans+1);
}
return 0;
}