某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后
他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。
现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
标签:puts csharp 范围 bsp char ring win 自己的 记忆化
算是最基础的区间dp类型了,设dp[i][j][k],表示[i,j]能否由k变来;
题目里面说明了每个字母都可以由两个字母变来,那么我们容易想到把[i,j]枚举断点分为两个区间,然后合并两个区间的信息,就是n^3的那种区间dp;
实现的话,区间dp最好都是写记忆化搜索,这样就不会有转移顺序的问题;
//MADE BY QT666
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int N=300;
bool dp[N][N][5],bj[N][N][5];
struct data{
int x,y;
};
vector<data> g[N];
char ch[N];
int s[N];
bool dfs(int l,int r,int p){
if(l==r){
bj[l][r][p]=1;
dp[l][r][p]=(s[l]==p);
return dp[l][r][p];
}
if(bj[l][r][p]) return dp[l][r][p];
for(int k=l;k<r;k++){
for(int i=0;i<g[p].size();i++){
dp[l][r][p]|=(dfs(l,k,g[p][i].x)&&dfs(k+1,r,g[p][i].y));
if(dp[l][r][p]) break;
}
if(dp[l][r][p]) break;
}
bj[l][r][p]=1;return dp[l][r][p];
}
void read(int xh,int sz){
for(int i=1;i<=sz;i++){
scanf("%s",ch+1);int x,y;
if(ch[1]==‘W‘) x=1;
if(ch[1]==‘I‘) x=2;
if(ch[1]==‘N‘) x=3;
if(ch[1]==‘G‘) x=4;
if(ch[2]==‘W‘) y=1;
if(ch[2]==‘I‘) y=2;
if(ch[2]==‘N‘) y=3;
if(ch[2]==‘G‘) y=4;
g[xh].push_back((data){x,y});
}
}
int main(){
int w,i,n,g;
scanf("%d%d%d%d",&w,&i,&n,&g);
read(1,w);read(2,i);read(3,n);read(4,g);
scanf("%s",ch+1);int len=strlen(ch+1);
for(int i=1;i<=len;i++){
if(ch[i]==‘W‘) s[i]=1;
if(ch[i]==‘I‘) s[i]=2;
if(ch[i]==‘N‘) s[i]=3;
if(ch[i]==‘G‘) s[i]=4;
}
int flg=0;
for(int i=1;i<=4;i++){
if(dfs(1,len,i)){
if(i==1) cout<<"W";
if(i==2) cout<<"I";
if(i==3) cout<<"N";
if(i==4) cout<<"G";
flg=1;
}
}
if(!flg) puts("The name is wrong!");
return 0;
}
标签:puts csharp 范围 bsp char ring win 自己的 记忆化
原文地址:http://www.cnblogs.com/qt666/p/7667914.html