UVA - 1625 Color Length
Color Length
\(problem:\)
给出两个颜色序列,长度分别为N,M,现在要将它们合并成一个新序列,每次可以将把一个序列的开头颜色放入新序列的尾部
记st(c)表示新序列中颜色c第一次出现的位置,ed(c)表示新序列中颜色c最后一次出现的位置
记L(c)=ed(c)-st(c),现在要最小化\(\sum_{c}L(c)\)
\(data\) \(range:\)
\(N,M<=5*10^3\)
\(solution:\)
太菜了,看了题解才明白神仙做法
考虑到这题是一个dp
根据套路记\(dp_{i,j}\)表示第一个序列已经将i个元素加入新序列,第二个序列已经将j个元素加入新序列时的最小代价
然后发现,,怎么转移??!!
那么我们再记\(cost_{i,j}\)表示此时的还没有结束的颜色的数量(就是这个颜色不是第一个也不是最后一个)
那么就有转移方程:
\(dp_{i,j}=min(dp_{i-1,j}+cost_{i-1,j},dp_{i,j-1}+cost_{i,j-1})\)
最后一步:如何求出\(cost_{i,j}\)?
可以预处理每个颜色分别在两个序列(分别设为a,b)中第一次和最后一次出现的位置
我们考虑\(cost_{i,j-1}->cost_{i,j}(cost_{i-1,j}->cost_{i,j}同理)\)
如果b_j是这个颜色在b中第一次出现的时候,倘若此时a还没有加入这个颜色,那么\(cost_{i,j}=cost_{i,j-1}+1\)
如果b_j是这个颜色在b中最后一次出现的时候,倘若此时a已经加完了这种颜色,那么\(cost_{i,j}=cost_{i,j-1}-1\)
\(space\) \(time\) \(complexity:\)
\(space\)&\(time:\) \(O(n*m)\)
\(note:\)
数组初始化又写炸了啊啊啊
\(code:\)
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5,Z=30;
int t,lena,lenb,sta[Z],eda[Z],stb[Z],edb[Z];
int dp[N][N],cost[N][N];
char a[N],b[N];
inline void pre()
{
for(int i=0;i<=lena;++i)
for(int j=0;j<=lenb;++j)
dp[i][j]=1e9,cost[i][j]=0;
fill(sta,sta+Z,lena+1),fill(eda,eda+Z,-1),
fill(stb,stb+Z,lenb+1),fill(edb,edb+Z,-1);
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%s%s",a+1,b+1);
lena=strlen(a+1),lenb=strlen(b+1);
pre();
for(char ch='A';ch<='Z';++ch)
{
for(int i=1;i<=lena;++i)
if(a[i]==ch){sta[ch-'A']=i;break;}
for(int i=lena;i>=1;--i)
if(a[i]==ch){eda[ch-'A']=i;break;}
for(int i=1;i<=lenb;++i)
if(b[i]==ch){stb[ch-'A']=i;break;}
for(int i=lenb;i>=1;--i)
if(b[i]==ch){edb[ch-'A']=i;break;}
}
dp[0][0]=cost[0][0]=0;
for(int i=0;i<=lena;++i)
for(int j=0;j<=lenb;++j)
{
if(!i&&!j)continue;
int c1=a[i]-'A',c2=b[j]-'A';
if(i)
{
cost[i][j]=cost[i-1][j];
dp[i][j]=min(dp[i-1][j]+cost[i-1][j],dp[i][j]);
if(i==sta[c1]&&j<stb[c1])++cost[i][j];
if(i==eda[c1]&&j>=edb[c1])--cost[i][j];
}
if(j)
{
cost[i][j]=cost[i][j-1];
dp[i][j]=min(dp[i][j-1]+cost[i][j-1],dp[i][j]);
if(i<sta[c2]&&j==stb[c2])++cost[i][j];
if(i>=eda[c2]&&j==edb[c2])--cost[i][j];
}
}
printf("%d\n",dp[lena][lenb]);
}
return 0;
}
NO PAIN NO GAIN