Cars painted in different colors are moving in a row on the road as
shown in Figure 1. The color of each car is represented by a single
character and the distance of two adjacent cars is assumed to be 1.
Figure 1 shows an example of such cars on the road. For convenience,
the numbers in Figure 1 represent the locations of each car. Figure 1.
Cars in different colors on the road For any color c , location ( c )
represents set of the locations of the cars painted in color c and
color length L ( c ) is de ned as follows: L ( c ) = max location ( c
)
动态规划。
dp[i][j]表示两个字符串分别进行到第i位和第j位的最小费用。
那么一定是从dp[i][j-1]或dp[i-1][j]转移而来。因为每个颜色的长度只和开始位置和结束位置有关,所以从某一个位置转移而来的话,该位置所有已开始而未结束的颜色的长度都要加一。
那么就需要预处理出每个位置已开始而未结束的颜色的个数。不妨记为cnt[i][j],则一定从cnt[i-1][j]或cnt[i][j-1]转移而来。注意这一次不是取最小值,而是在有意义的情况下任取即可,因为每个位置的个数是一定的,不存在最优化问题。
为了求cnt数组,有需要进行预处理。记下每个字符串中每种颜色的起始和结束位置,不妨考虑由cnt[i-1][j]转移而来,cnt[i][j-1]同理。
如果i是某个颜色的起始的话,那就在之前基础上加一。如果是末尾的话,要减一。【注意这里说的起始和末尾是整个序列的,而不是他所在字符串的。】
得到cnt数组之后,便可以计算dp数组了。
dp[i][j]=min(dp[i-1][j]+cnt[i][j-1],dp[i][j-1]+cnt[i][j-1])。
注意边界条件。
注意区间首尾和边界。
不要用memset。(除非用滚动数组)
#include<cstdio>
#include<cstring>
#define M(a) memset(a,0,sizeof(a))
int min(int x,int y){return x<y?x:y;}
int dp[5010][5010],bg[2][30],ed[2][30],cnt[5010][5010];
char s[2][5010];
const int oo=0x7f7f7f7f;
int main()
{
int i,j,k,l[2],m,n,p,q,x,y,z,T,cnt1,cnt2;
char c;
scanf("%d",&T);
while (T--)
{
M(bg);
M(ed);
for (i=0;i<2;i++)
{
scanf("%s",s[i]+1);
l[i]=strlen(s[i]+1);
for (j=1;j<=l[i];j++)
if (!bg[i][s[i][j]-'A'+1])
bg[i][s[i][j]-'A'+1]=j;
for (j=l[i];j>=1;j--)
if (!ed[i][s[i][j]-'A'+1])
ed[i][s[i][j]-'A'+1]=j;
}
for (i=0;i<=l[0];i++)
for (j=0;j<=l[1];j++)
if (i)
cnt[i][j]=cnt[i-1][j]
+(bg[0][s[0][i]-'A'+1]==i&&(bg[1][s[0][i]-'A'+1]>j||bg[1][s[0][i]-'A'+1]==0))
-(ed[0][s[0][i]-'A'+1]==i&&(ed[1][s[0][i]-'A'+1]<=j||ed[1][s[0][i]-'A'+1]==0));
else
if (j)
cnt[i][j]=cnt[i][j-1]
+(bg[1][s[1][j]-'A'+1]==j&&(bg[0][s[1][j]-'A'+1]>i||bg[0][s[1][j]-'A'+1]==0))
-(ed[1][s[1][j]-'A'+1]==j&&(ed[0][s[1][j]-'A'+1]<=i||ed[0][s[1][j]-'A'+1]==0));
for (i=0;i<=l[0];i++)
for (j=0;j<=l[1];j++)
if (i||j)
{
x=y=oo;
if (i) x=dp[i-1][j]+cnt[i-1][j];
if (j) y=dp[i][j-1]+cnt[i][j-1];
dp[i][j]=min(x,y);
}
printf("%d\n",dp[l[0]][l[1]]);
}
}