【題解】 bzoj1055: [HAOI2008]玩具取名 (動態規劃)
阿新 • • 發佈:2018-05-12
isp haoi2008 name div clas tro 規劃 pac att
bzoj1055,懶得復制,戳我戳我
Solution:
- 區間動規(以後開始動規會在solution前面標註是啥動規
- 我覺的這道題挺難想了,但其實狀態定義了一下子就出來了
(還是不行啊) - 我們定義狀態\(dp[i][j][sta]\),表示在\(i\)到\(j\)區間可不可以合成字符\(sta\),這裏我們用\(1\)表示\(W\),\(2\)表示\(I\)依次類推
- 轉移方程就很簡單了:(註意有一個是\(1\)就是\(1\),然後可以\(break\)了) \[dp[i][j][sta]=max((dp[i][k][ left ]),(dp[k+1][j][ right] ))\].
或者說\[dp[i][j][sta]=((dp[i][k][ left ])\&(dp[k+1][j][ right] ))\] - \(left\)表示某個合成\(sta\)的方法中左邊那個字符代表的數字,\(right\)就是右邊那個
Attention:
- 註意無解情況輸出
Code:
//It is coded by Ning_Mew on 5.10
#include<bits/stdc++.h>
using namespace std;
const int maxn=207;
int n[5],ll=0;
int s[10][20][5];
int goal[maxn];
string ss;
int dp[maxn][maxn][10];
int num[30];
int main(){
scanf("%d%d%d%d ",&n[1],&n[2],&n[3],&n[4]);
num[‘W‘-‘A‘+1]=1;num[‘I‘-‘A‘+1]=2;
num[‘N‘-‘A‘+1]=3;num[‘G‘-‘A‘+1]=4;
for(int i=1;i<=4;i++){
for(int j=1;j<=n[i];j++){
cin>>ss;
s[i][j][1]=num[ss[0]-‘A‘+1];
s[i][j][2]=num[ss[1]-‘A‘+1];
}
}
cin>>ss;ll=ss.length();
for (int i=0;i<ll;i++){
dp[i][i][ num[ss[i]-‘A‘+1] ]=1;
goal[i]=num[ss[i]-‘A‘+1];
}
for(int len=2;len<=ll;len++){
for(int i=0;i<=ll-len;i++){
int ss=i,tt=i+len-1;
for(int j=ss;j<=tt-1;j++){//中間的斷點
for(int sta=1;sta<=4;sta++){
for(int k=1;k<=n[sta];k++){
int ll=s[sta][k][1],rr=s[sta][k][2];
if(dp[ss][j][ll]==1 && dp[j+1][tt][rr]==1){dp[ss][tt][sta]=1;break;}
}
}
}
}
}
bool out=false;
for(int i=1;i<=4;i++){
if(dp[0][ll-1][i]){
if(i==1)printf("W"),out=true;if(i==2)printf("I"),out=true;
if(i==3)printf("N"),out=true;if(i==4)printf("G"),out=true;
}
}
if(!out)printf("The name is wrong!");printf("\n");
return 0;
}
【題解】 bzoj1055: [HAOI2008]玩具取名 (動態規劃)