uva 1625 Color Length (dp)

题意:有两个字符串,从两个字符串中取字符组成一个新串,并规定跨度L(c)表示该字符在新串中最大位置和最小位置的差,最终求所有L(c)的和;

解:这个题的思路好想,就是用dp[i][j]来表示当前已经从第一个中取了i个从第二个中取了j个字符后的最小跨度,但麻烦的就是怎么实现这个状态,每次都重新算一遍每个的跨度时间肯定承受不了,所以有个简便的方法就是求当前已经有多少字符已经被取了但是最后一个该字符还没有被取到,因为只要有一个字符没有结束被取,那么每取一个字符该字符的跨度都要+1,所以当前没有结束的字符的个数就应该是取一个字符后总跨度应该加的,这里可以用一个c数组表示,然后每次都去更新这个数组的状态就好了;

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxed=5000+10;
int dp[maxed][maxed],sta1[27],sta2[27],en1[27],en2[27],c[maxed][maxed];
char s1[maxed],s2[maxed];
int main()
{
    int n;
    scanf("%d",&n);
    while(n--){
        scanf("%s",s1+1);
        scanf("%s",s2+1);
        memset(sta1,0x3f3f3f3f,sizeof(sta1));
        memset(sta2,0x3f3f3f3f,sizeof(sta2));
        memset(en1,0,sizeof(en1));
        memset(en2,0,sizeof(en2));
        int len1=strlen(s1+1),len2=strlen(s2+1);
        for(int i=1;i<=len1;i++){
            sta1[s1[i]-'A']=min(sta1[s1[i]-'A'],i);
            en1[s1[i]-'A']=max(en1[s1[i]-'A'],i);
        }
        for(int i=1;i<=len2;i++){
            sta2[s2[i]-'A']=min(sta2[s2[i]-'A'],i);
            en2[s2[i]-'A']=max(en2[s2[i]-'A'],i);
        }
        for(int i=0;i<=len1;i++)
            for(int j=0;j<=len2;j++){
                 if(!i&&!j)
                    continue;
                 int m1=1<<30,m2=1<<30;
                 if(i)
                    m1=dp[i-1][j]+c[i-1][j];
                 if(j)
                    m2=dp[i][j-1]+c[i][j-1];
                 dp[i][j]=min(m1,m2);
                 //cout<<"sdasdasd"<<dp[i][j]<<endl;
                 if(dp[i][j]==m1){    //这里就是去每次都更新一下c数组
                    c[i][j]=c[i-1][j];
                    if(sta1[s1[i]-'A']==i&&sta2[s1[i]-'A']>j)
                        c[i][j]++;
                    if(en1[s1[i]-'A']==i&&en2[s1[i]-'A']<=j)
                        c[i][j]--;
                 }
                 else if(dp[i][j]==m2){
                    c[i][j]=c[i][j-1];
                    if(sta2[s2[j]-'A']==j&&sta1[s2[j]-'A']>i)
                        c[i][j]++;
                    if(en2[s2[j]-'A']==j&&en1[s2[j]-'A']<=i)
                        c[i][j]--;
                 }
            }
        printf("%d\n",dp[len1][len2]);
    }
    return 0;
}
这个代码感觉时间卡的刚刚好,因为我第一次多加了两个memset,就超时了,因为之前也因为这个超时过,所以删掉了两个memset,结果就过了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值