1. 程式人生 > >【題解】 bzoj1055: [HAOI2008]玩具取名 (動態規劃)

【題解】 bzoj1055: [HAOI2008]玩具取名 (動態規劃)

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]玩具取名 (動態規劃)