UVA-1625 Color Length

来源:互联网 发布:cn 域名 编辑:程序博客网 时间:2024/04/30 16:28

Brief  description 

这里直接copy紫书上面的文字了。

输入2个长度为n和m(n,m<=5000)的颜色序列,要求按照顺序合并成同一个序列,即每次可以把一个序列的开头的颜色放到新序列的尾部。

例如,两个颜色序列GBBY和YRRGB,至少有2种合并结果:GBYBRYBGB和YRRGGBBYB。对于每个颜色c来说,其跨度L(c)等于最大位置与最小位置之差。

你的任务是找一种合并方式,使得所有的L(c)的总和最小。


Algorithm  analyse


在没有看题解之前不难想到一个大致的状态转移方程dp[i][j]=min(dp[i-1][j]+m,dp[i][j-1]+k),但是m,k在状态转移时候的加入字母导致的一些变化量无从下手。还有一些临界条件的分析很混乱。所以很仔细地看了刘汝佳老师的代码.


Code

#include<cstdio>#include<algorithm>#include<cstring>#include<algorithm>using namespace std;const int maxn=5050;const int INF = 1000000000;char p[maxn],q[maxn];int sp[26],sq[26],ep[26],eq[26];int d[2][maxn],c[2][maxn];int main(){int T;scanf("%d",&T);while(T--){scanf("%s%s",p+1,q+1);int n=strlen(p+1);int m=strlen(q+1);for(int i=1;i<=n;i++)  p[i]-='A';for(int i=1;i<=m;i++)  q[i]-='A';for(int i=0;i<26;i++){sp[i]=sq[i]=INF;ep[i]=eq[i]=0;}for(int i=1;i<=n;i++){sp[p[i]]=min(sp[p[i]],i);ep[p[i]]=i;}for(int i=1;i<=m;i++){sq[q[i]]=min(sq[q[i]],i);eq[q[i]]=i;}memset(d,0,sizeof(d));memset(c,0,sizeof(c));int t=0;for(int i=0;i<=n;i++)        {        for(int j=0;j<=m;j++)    {    if(!i&&!j) continue;  int v1,v2;  v1=v2=INF;  if(i)  v1=d[t^1][j]+c[t^1][j];              if(j) v2=d[t][j-1]+c[t][j-1];  d[t][j]=min(v1,v2);  if(i)  {    c[t][j]=c[t^1][j];    if(sp[p[i]]==i&&sq[p[i]]>j)  c[t][j]++;    if(ep[p[i]]==i&&eq[p[i]]<=j)   c[t][j]--;  }  else if(j)  {    c[t][j]=c[t][j-1];    if(sq[q[j]]==j&&sp[q[j]]>i)  c[t][j]++;    if(eq[q[j]]==j&&ep[q[j]]<=i)   c[t][j]--;  }    }t^=1;         }        printf("%d\n",d[t^1][m]);}return 0;}

Summary

1.掌握记录每个颜色在两个序列的中的开始和结束位置的方法.

2.对于临界条件的把握.这里有两点 a. i,j分别为0的时候的讨论

                                                             b. 开始与结束的判断.例如在代码

                                  if(sp[p[i]]==i&&sq[p[i]]>j)  c[t][j]++;                                  if(ep[p[i]]==i&&eq[p[i]]<=j) c[t][j]++;

                                                             为何不是sq>=然后再eq<?

对于每个颜色,一定要是最先插入,最后结束

j表示当前第2列放入了j个颜色. sq==的话,表示这个颜色已经有,eq==的话,表示这个颜色还没结束.

3.滚动数组:

   目的是节约空间消耗.当当前的变化只与上一个相关时,可以这么使用。看这个简便理解。

http://blog.csdn.net/niushuai666/article/details/6677982

点击打开链接

  

0 0
原创粉丝点击