• 玩具取名


    区间dp

    思路挺好想的,不过实现......极其鬼畜
    令dp[i][j][k]表示i ->j区间能否合为k,pan[b][c]表示b,c字母能合并为哪些字母。
    转移方程:$$dp[l][r][a]=dp[l][r][a] | (dp[l][k][b]cap dp[k+1][r][c]) Kepsilon [l,r],pan[b][c]==a$$

    code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #define max(a,b) a>b?a:b
    #define maxn 102
    using namespace std;
    int w,ii,n,g;
    bool dp[206][206][7],t[7][17][17];
    int it[7][18][5],num[17];
    char str[206];
    inline int make(char tmp)
    {
    	if (tmp=='W') return 1;
    	if (tmp=='I') return 2;
    	if (tmp=='N') return 3;
    	if (tmp=='G') return 4;
    	return 0;
    }
    int main()
    {
    	cin>>w>>ii>>n>>g;
    	for (int i=1;i<=w;++i)
    	{	
    		char tm[5];
    		scanf("%s",tm+1);
    		t[1][make(tm[1])][make(tm[2])]=1;
    		it[1][++num[1]][1]=make(tm[1]),it[1][num[1]][2]=make(tm[2]);
    	} 
    	for (int i=1;i<=ii;++i)
    	{	
    		char tm[5];
    		scanf("%s",tm+1);
    		t[2][make(tm[1])][make(tm[2])]=1;	
    		it[2][++num[2]][1]=make(tm[1]),it[2][num[2]][2]=make(tm[2]);
    	} 
    	for (int i=1;i<=n;++i)
    	{	
    		char tm[5];
    		scanf("%s",tm+1);
    		t[3][make(tm[1])][make(tm[2])]=1;
    		it[3][++num[3]][1]=make(tm[1]),it[3][num[3]][2]=make(tm[2]);	
    	} 
    	for (int i=1;i<=g;++i)
    	{	
    		char tm[5];
    		scanf("%s",tm+1);
    		t[4][make(tm[1])][make(tm[2])]=1;
    		it[4][++num[4]][1]=make(tm[1]),it[4][num[4]][2]=make(tm[2]);	
    	} 
    	scanf("%s",str+1);	
    	int len=strlen(str+1);
    	for (int i=1;i<=len;++i)
    	{
    		dp[i][i][make(str[i])]=1;
    	}
    	for (int i=2;i<=len;++i) 
    	for (int j=1;j<=len-i+1;++j)
    	{
    		int k=j+i-1;
    		for (int l=j;l<=k;++l) 
    		for (int m=1;m<=4;++m)
    		for (int o=1;o<=num[m];++o)
            dp[j][k][m]|=(dp[j][l][it[m][o][1]] & dp[l+1][k][it[m][o][2]]);
    	}
    	int ans[5];
    	ans[1]=ans[2]=ans[3]=ans[4]=0;
    	for (int i=1;i<=4;++i)
    	{
    		if (dp[1][len][i]) ans[i]=1;
    	}
    	if (!ans[1]&&!ans[2]&&!ans[3]&&!ans[4]) cout<<"The name is wrong!";
    	else 
    	{
    		if (ans[1]) cout<<"W";
    		if (ans[2]) cout<<"I";
    		if (ans[3]) cout<<"N";
    		if (ans[4]) cout<<"G";
     	}
    	return 0;
    }
    

    收获:大力dp就好了

  • 相关阅读:
    单工、半双工和双工通信
    Callable和Future
    有状态和无状态服务
    paxos协议
    OOP面向对象编程的三大特性
    php工厂模式
    php 观察者模式
    php的单例模式
    php是单继承还是多继承呢?
    MySQL—内连接join 和外连接 left join 区别 交叉连接 a,b cross joni union 联合
  • 原文地址:https://www.cnblogs.com/bullshit/p/9813138.html
Copyright © 2020-2023  润新知