题目只有PDF格式,就不复制了,不过话说这道题真的很好看(因为有颜色的小车很可爱吧)。
题意:给你两个序列,分别只有大写字母,你需要把他们按照顺序变成一列,使得这列每种字母的最前面的和最后面的距离差 的和最小。
思路:dp[i][j][0]表示整合第一列的前i个字符和第二列的前j个字符,且最后一个字符是第一列的的最小权值,同理dp[i][j][1]表示最后一个字符使第二列的的最小权值。每次增加一个字符的时候,遍历出它前面和后面是不是有同样颜色的车,如果有的话,权值+1。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s1[5010],s2[5010];
int dp[5010][5010][2],num1[5010][26],num2[5010][26],sum[26],INF=1000000000;
int main()
{ int t,i,j,k,n,m,p;
scanf("%d",&t);
while(t--)
{ scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1);
m=strlen(s2+1);
for(i=1;i<=n;i++)
{ for(j=0;j<=25;j++)
num1[i][j]=num1[i-1][j];
num1[i][s1[i]-'A']++;
}
for(i=1;i<=m;i++)
{ for(j=0;j<=25;j++)
num2[i][j]=num2[i-1][j];
num2[i][s2[i]-'A']++;
}
for(i=0;i<=25;i++)
sum[i]=num1[n][i]+num2[m][i];
dp[0][0][0]=0;
dp[0][0][1]=0;
for(i=1;i<=n;i++)
{ dp[i][0][0]=dp[i-1][0][0];
dp[i][0][1]=INF;
for(k=0;k<=25;k++)
{ p=num1[i-1][k];
if(p>0 && sum[k]-p>0)
dp[i][0][0]++;
}
}
for(i=1;i<=m;i++)
{ dp[0][i][1]=dp[0][i-1][1];
dp[0][i][0]=INF;
for(k=0;k<=25;k++)
{ p=num2[i-1][k];
if(p>0 && sum[k]-p>0)
dp[0][i][1]++;
}
}
for(i=1;i<=n;i++)
{ for(j=1;j<=m;j++)
{ dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1]);
dp[i][j][1]=min(dp[i][j-1][0],dp[i][j-1][1]);
for(k=0;k<=25;k++)
{ p=num1[i-1][k]+num2[j][k];
if(p>0 && sum[k]-p>0)
dp[i][j][0]++;
p=num1[i][k]+num2[j-1][k];
if(p>0 && sum[k]-p>0)
dp[i][j][1]++;
}
}
}
printf("%d\n",min(dp[n][m][0],dp[n][m][1]));
}
}