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


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

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

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

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

    则只有\(5\geq a\geq b\geq c\geq d\geq e\geq 0\)的状态才是合法的。

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

    代码:

    #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;
    }
    

  • 相关阅读:
    项目Alpha冲刺(团队)-第七天冲刺
    NOIP模拟赛[补档]
    关于补档
    noip2017集训测试赛(三) Problem B: mex [补档]
    初赛准备 [补档]
    记录 [补档]
    Leave It Behind and Carry On ---- 高一下期末考反思 [补档]
    NOIP 2017 赛后反思 [补档]
    囤题 [补档]
    组合游戏学习笔记 [补档]
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597620.html
Copyright © 2020-2023  润新知