習題:Trucks and Cities(DP)
阿新 • • 發佈:2020-07-29
題目
思路
我們考慮如果簡單一點的情況
設\(f[i][j][c]\)表示區間\(i到j\)能不能用字元\(c\)構成
我們設\(c\)能拓展成\(a\)和\(b\)
\(f[i][j][c]|=(f[i][k][a]\&f[k+1][j][b])\)
接著我們考慮對於他們的祖先一個字元一個字元的加入
設\(dp[i][j]\)為\(s_1\)的前i位和\(s_2\)的前\(j\)位的最小祖先長度,
\(dp[i][j]=min\{dp[i_1][j_1]+1[f1[i_1][i][c]\&f2[i_2][j][c]]\}\)
即一個字元拓展成為一個區間
總時間複雜度即為\(O(n^4)\)
程式碼
#include<iostream> #include<cstring> using namespace std; struct node { char a; char b,c; }op[55]; int n; char a[55],b[55]; int lena,lenb; int f1[55][55][30],f2[55][55][30]; //區間i到j能否用k構造出來 int dp[55][55]; //a的前i個數和b的前j個數的最小長度 int dfs(int f[][55][30],char *a,int l,int r,int ch) { if(l==r&&a[l]==ch) f[l][r][ch]=1; if(f[l][r][ch]!=-1) return f[l][r][ch]; for(int i=1;i<=n;i++) if(op[i].a==ch) for(int j=l;j<r;j++) if(dfs(f,a,l,j,op[i].b)==1&&dfs(f,a,j+1,r,op[i].c)==1) { f[l][r][ch]=1; return 1; } f[l][r][ch]=0; return 0; } int solve(int la,int lb) { if(dp[la][lb]!=-1) return dp[la][lb]; dp[la][lb]=(1<<30); for(int k=1;k<=26;k++) for(int i=0;i<la;i++) for(int j=0;j<lb;j++) if(dfs(f1,a,i+1,la,k)==1&&dfs(f2,b,j+1,lb,k)==1) dp[la][lb]=min(dp[la][lb],solve(i,j)+1); return dp[la][lb]; } int main() { ios::sync_with_stdio(false); memset(f1,-1,sizeof(f1)); memset(f2,-1,sizeof(f2)); memset(dp,-1,sizeof(dp)); cin>>(a+1)>>(b+1); lena=strlen(a+1); lenb=strlen(b+1); for(int i=1;i<=lena;i++) a[i]-='a'-1; for(int i=1;i<=lenb;i++) b[i]-='a'-1; cin>>n; for(int i=1;i<=n;i++) { string a; cin>>a; a[0]-='a'-1; a[3]-='a'-1; a[4]-='a'-1; op[i].a=a[0]; op[i].b=a[3]; op[i].c=a[4]; } dp[0][0]=0; if(solve(lena,lenb)==1073741824) cout<<"-1"; else cout<<solve(lena,lenb)<<endl; return 0; }