uva1625 color length

来源:互联网 发布:崖山之后无中国 知乎 编辑:程序博客网 时间:2024/04/27 20:02

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]]);    }}
1 0
原创粉丝点击