1. 程式人生 > >[UVA1625]Color Length

[UVA1625]Color Length

方式 print 入門經典 ron lex Go tor code 劉汝佳

題面在這裏

description

輸入兩個長度分別為\(n\)\(m\)的顏色序列,要求按順序合並成同一個序列,即每次可以把一個序列開頭的顏色放到新序列的尾部。
對於每個顏色\(c\)來說,其跨度\(L(c)\)等於最大位置和最小位置之差。
你的任務是找一種合並方式,使得所有\(L(c)\)的總和最小。

——摘自《算法競賽入門經典(第2版)》,劉汝佳 著

data range

\[n,m\le 5000\]

solution

序列合並問題,使用\(f[i][j]\)表示第一個序列前\(i\)個顏色和第二個序列前\(j\)個顏色合並之後的最小貢獻
轉移時每次往後添加兩個序列首端的其中一個字符;

雖然通過這種狀態無法得知每種顏色在這些方案中的始末位置,但我們仍然可以計算答案——未來費用的動態規劃問題,提前計算貢獻!


即每次往序列尾端添上一個顏色的時候,我們可以提前加上仍未終結的顏色的貢獻

我們使用輔助數組\(g[i][j]\)表示第一個序列前\(i\)個顏色和第二個序列前\(j\)個顏色合並之後還未結束的顏色數量,於是可以這樣轉移:

\[f[i][j]=min\{f[i-1][j]+g[i-1][j],f[i][j-1]+g[i][j-1]\}\]

答案存儲在\(f[n][m]\),做完啦

code

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> //#define TEST #define FILE "a" #define mp make_pair #define pb push_back #define RG register
#define il inline using namespace std; typedef unsigned long long ull; typedef vector<int>VI; typedef long long ll; typedef double dd; const int inf=1e9+7; const int mod2=998244353; const int rev2=332748118; const int mod1=1e9+7; const int N=5010; const dd eps=1e-10; const ll INF=1e18; il ll read(){ RG ll data=0,w=1;RG char ch=getchar(); while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar(); if(ch==‘-‘)w=-1,ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)data=data*10+ch-48,ch=getchar(); return data*w; } il void file(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); } int n,m,g[N][N],f[N][N],tot[400],cnt[400]; char a[N],b[N]; il int solve(){ memset(tot,0,sizeof(tot)); for(RG int i=1;i<=n;i++)tot[a[i]]++; for(RG int i=1;i<=m;i++)tot[b[i]]++; for(RG int i=0;i<=n;i++){ memset(cnt,0,sizeof(cnt)); g[i][0]=0; for(RG int j=1;j<=i;j++){ if(!cnt[a[j]])g[i][0]++; cnt[a[j]]++; if(cnt[a[j]]==tot[a[j]])g[i][0]--; } for(RG int j=1;j<=m;j++){ g[i][j]=g[i][j-1]; if(!cnt[b[j]])g[i][j]++; cnt[b[j]]++; if(cnt[b[j]]==tot[b[j]])g[i][j]--; } } f[0][0]=0; for(RG int i=0;i<=n;i++) for(RG int j=0;j<=m;j++){ if(i||j)f[i][j]=2147484647/2; if(i)f[i][j]=min(f[i][j],f[i-1][j]+g[i-1][j]); if(j)f[i][j]=min(f[i][j],f[i][j-1]+g[i][j-1]); } return f[n][m]; } int main() { RG int T=read(); while(T--){ scanf("%s%s",a+1,b+1);n=strlen(a+1);m=strlen(b+1); printf("%d\n",solve()); } return 0; }

[UVA1625]Color Length