您的位置:首页 > 其它

Uva 1625,颜色的长度

2016-10-24 20:04 218 查看
类似于LCS的动态规划,指标函数的分解。

题目链接:https://uva.onlinejudge.org/external/16/1625.pdf

题目大意:两个颜色序列,将他们合并,合并的时候,每次都从开头拿颜色,对于每一个颜色c来说,都有他的跨度l(c),就是最后的位置与最前的位置的差值,就怎样的排列是的所有l(c)总和最小。

分析:从两个串中随机拿字符,解答树是特别大的。

d(i,j) p拿前 I 个字符, q拿前 j 个字符 所要的代价。

n,m<=5000,二维数组改成滚动数组。

这个时候,不是等到一个颜色全部移动玩了之后再算跨度。而是,只要多少种颜色已经开始但尚未结束,L(c) + 1;

重点再与求代价C。首先计算全部移动Q,只要是该字符开头,代价就加一,但是如果刚好是最后一个就恢复。然后再推数组P时,就可以直接利用已经计算好的c代价数组,只需要根据他更新由于i的加入使得增加的代价。

#include <bits/stdc++.h>
using namespace std;

#define maxn 5005
#define INF 0x3f3f3f3f

char p[maxn],q[maxn];
int sp[26],ep[26],sq[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(c,0,sizeof(c));
memset(d,0,sizeof(d));
int t = 1;
//dp
for(int i = 0; i <= n; i++)
{
for(int j = 0; j <= m; j++)
{
if(!i && !j) continue;

int v1 = INF, v2 = INF;
if(i) v1 = d[t^1][j] + c[t^1][j]; // 从P上面移动
if(j) v2 = d[t][j - 1] + c[t][j - 1]; // 从Q上面移动
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;
}


两个颜色序列,将他们合并,合并的时候,每次都从开头拿颜色,对于每一个颜色c来说,都有他的跨度l(c),就是最后的位置与最前的位置的差值,就怎样的排列是的所有l(c)总和最小。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: