[USACO5.5]贰五语言Two Five

LXX.[USACO5.5]贰五语言Two Five

这题已经在我的收藏夹里面吃了大半年的灰了

发现当表格填到某个地方后,它一定是呈现出一条逐行递减的轮廓线的。

因此,我们设f[a][b][c][d][e]表示第1行填了a个……第5行填了e个的方案数。

则只有5abcde0的状态才是合法的。

用记忆化搜索实现。之后对于每一位确定应该填什么即可。复杂度257(上界,真实复杂度远远不到)

代码:

#include<bits/stdc++.h>
using namespace std;
int f[6][6][6][6][6],n;
char tp[2],s[100],t[100];
bool che(char x,int y){
	return (!x)||x=='A'+y;
}
int dfs(int a,int b,int c,int d,int e){
	if(a+b+c+d+e==25)return 1;
	int &ret=f[a][b][c][d][e];
	if(ret)return ret;
	if(a<5&&che(s[a],a+b+c+d+e))ret+=dfs(a+1,b,c,d,e);
	if(b<a&&che(s[b+5],a+b+c+d+e))ret+=dfs(a,b+1,c,d,e);
	if(c<b&&che(s[c+10],a+b+c+d+e))ret+=dfs(a,b,c+1,d,e);
	if(d<c&&che(s[d+15],a+b+c+d+e))ret+=dfs(a,b,c,d+1,e);
	if(e<d&&che(s[e+20],a+b+c+d+e))ret+=dfs(a,b,c,d,e+1);
//	printf("%d %d %d %d %d:%d\n",a,b,c,d,e,res);
	return ret;
}
bool used[100];
int main(){
	scanf("%s",tp);
	if(tp[0]=='N'){
		scanf("%d",&n);
		int sum=0;
		for(int i=0;i<25;i++)for(s[i]='A';s[i]<='Z';s[i]++){
			if(used[s[i]])continue;
			used[s[i]]=true;
			memset(f,0,sizeof(f));
			int tmp=dfs(0,0,0,0,0);
			if(sum+tmp>=n)break;
			sum+=tmp;
			used[s[i]]=false;
		}
		printf("%s\n",s);
	}else{
		scanf("%s",t);
		int res=0;
		for(int i=0;i<25;i++)for(s[i]='A';s[i]<t[i];s[i]++){
			memset(f,0,sizeof(f));
			res+=dfs(0,0,0,0,0); 
		}
		printf("%d\n",res+1);
	}
	return 0;
}

posted @   Troverld  阅读(61)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示