codeforce_exercise_r9

Color Length(UVa-1625) :

问题描述

题目简述

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 thelocations of each car.
For any color c, location© represents set of the locations of the cars painted in color c and color length L(a) is defined as follows:
L(a) = max location(a) − min location(a)
Given two character strings which represent the color information of the cars in the two lanes before merging, write a program to find the sum of color lengths obtained from the character string, which is the color information of cars after merging, such that the sum of color lengths is minimized.

输入/输出格式

输入格式:
Your program is to read from standard input. The input consists of T test cases. The number of test
cases T is given in the first line of the input. Each test case consists of two lines. In the first line, a character string of length n (1 ≤ n ≤ 5, 000) that is the color information of the cars in one lane before merging is given. In the second line, a character string of length m (1 ≤ m ≤ 5, 000) that is the color information of the cars in the other lane is given. Every color is represented as an uppercase letter in English, hence the number of colors is less than or equal to 26.
输出格式:
Your program is to read from standard input. Print exactly one line for each test case. The line should contain the sum of color lengths after merging the cars in the two lanes optimally as described above.

样例

输入样例:
2
AAABBCY
ABBBCDEEY
GBBY
YRRGB
输出样例:
10
12

问题分析

解题思路

可以设dp(i,j)为第一个字符串的前i个字符和第二个字符串的前j个字符合并后产生的最小的颜色长度。根据定义:
dp(i,j)=min(dp(i-1,j)+cnt(i-1,j),dp(i,j-1)+cnt(i,j-1))
且可以初始化dp(0,0)=0,其余均为inf,最后的结果为dp(n,m),n和m分别为两个字符串的长度。那么,重点就是如何判断每次迁移状态时,需要增加的长度数量。可以发现,增加的长度与当前已合并字符串中还没有全部加入字符串的字符种类相同。这样,只需要统计各个字符种类在两个字符串中第一个和最后一个出现的位置,即可判断。

参考代码
#include <iostream>
#include <cstring>

using namespace std;

const int inf=1000010;

char a[5050];
char b[5050];
int sa[100],sb[100],ea[100],eb[100];
int T;
int cnt[5050][5050];
int dp[5050][5050];

void init()
{
	memset(sa,inf,sizeof(sa));
	memset(sb,inf,sizeof(sb));
	memset(ea,0,sizeof(ea));
	memset(eb,0,sizeof(eb));
}

int main()
{
	scanf("%d",&T);
	while(T--)
	{
		init();
		scanf("%s",a+1);
		scanf("%s",b+1);
		int la=strlen(a+1);
		int lb=strlen(b+1);
		for(int i=1;i<=la;i++)
		{
			sa[a[i]]=min(sa[a[i]],i);
			ea[a[i]]=max(ea[a[i]],i);
		}
		for(int i=1;i<=lb;i++)
		{
			sb[b[i]]=min(sb[b[i]],i);
			eb[b[i]]=max(eb[b[i]],i);
		}
		cnt[0][0]=0;
		for(int i=0;i<=la;i++)
		{
			for(int j=0;j<=lb;j++)
			{
				if(i>0)
				{
					cnt[i][j]=cnt[i-1][j];
					if(sa[a[i]]==i&&sb[a[i]]>j) cnt[i][j]++;
					if(ea[a[i]]==i&&eb[a[i]]<=j) cnt[i][j]--;
				}
				if(j>0)
				{
					cnt[i][j]=cnt[i][j-1];
					if(sb[b[j]]==j&&sa[b[j]]>i) cnt[i][j]++;
					if(eb[b[j]]==j&&ea[b[j]]<=i) cnt[i][j]--;
				}
			}
		}
		dp[0][0]=0;
		for(int i=0;i<=la;i++)
		{
			for(int j=0;j<=lb;j++)
			{
			    if(i==0&&j==0) continue;
			    dp[i][j]=inf;
			    if(i) dp[i][j]=min(dp[i][j],dp[i-1][j]+cnt[i-1][j]);
			    if(j) dp[i][j]=min(dp[i][j],dp[i][j-1]+cnt[i][j-1]);
			}
		}
		printf("%d\n",dp[la][lb]);
	}
	return 0;
}

心得体会

报了几次T,主要是在初始化的时候由于dp矩阵太大,导致初始化时间很长。实际不初始化,而在dp的时候用到该状态时给它赋一个初值就能过了(实际上数据点规模要比5000小不少)。另外最好还是滚动数组,因为这里最后只是输出最小的颜色长度,用滚动数组省空间。总体来说还是比较顺利的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值