【UVa1625】颜色的长度
2016-09-21 19:07
316 查看
【问题描述】
输入两个颜色序列(只包含大写字母的字符串),要求按顺序合并成同一个序列,即每次可以把一个序列的开头的颜色放到新序列的尾部。
例如,两个颜色序列GBBY和YRRGB,至少有两种合并结果:GBYBRYRGB和YRRGGBBYB。对于每个颜色c来说,其跨度L(c)等于最大位置和最小位置之差,例如对于上面两种合并结果,每个颜色的L(c)和所有L(C)总和如下表:
你的任务是找一种合并方式,使得所有L(c)的总和最小。
【输入格式】
输入包含两行,每行一个只含大写字母的字符串,表示两个颜色序列。
【输出格式】
输出一个整数,表示L(c)总和的最小值。
【输入样例】
【样例1】
AAABBCY
ABBBCDEEY
【样例2】
GBBY
YRRGB
【输出样例】
【样例1】
10
【样例2】
12
【数据范围】
颜色序列的长度不超过5000。
紫书上的一个例题,根据求什么设什么的原则,设f(i,j)=两个颜色序列分别移走了i个元素和j个元素L(c)之和的最小值
本题子问题的分析(状态转移)是十分清晰的,因为每一次要么从第一个序列中取元素f(i-1,j),要么从第二个序列中取元素f(i,j-1),但是每一个的L(c)都显得难以计算,因为难以记录选出的元素是否在新的序列当中出现过,或者出现过却不知道出现的位置。按照紫书的分析,不应该直接去算L(c),而是按次累加那些已经开始但尚未结束的颜色种数,所以预处理算出c[i][j]即第一个序列中选i个,第二个序列中选j个时两个序列中已经出现但是没有结束的颜色总数,然后在dp时累加即可。
注意不用滚动会TLE哦~
输入两个颜色序列(只包含大写字母的字符串),要求按顺序合并成同一个序列,即每次可以把一个序列的开头的颜色放到新序列的尾部。
例如,两个颜色序列GBBY和YRRGB,至少有两种合并结果:GBYBRYRGB和YRRGGBBYB。对于每个颜色c来说,其跨度L(c)等于最大位置和最小位置之差,例如对于上面两种合并结果,每个颜色的L(c)和所有L(C)总和如下表:
你的任务是找一种合并方式,使得所有L(c)的总和最小。
【输入格式】
输入包含两行,每行一个只含大写字母的字符串,表示两个颜色序列。
【输出格式】
输出一个整数,表示L(c)总和的最小值。
【输入样例】
【样例1】
AAABBCY
ABBBCDEEY
【样例2】
GBBY
YRRGB
【输出样例】
【样例1】
10
【样例2】
12
【数据范围】
颜色序列的长度不超过5000。
紫书上的一个例题,根据求什么设什么的原则,设f(i,j)=两个颜色序列分别移走了i个元素和j个元素L(c)之和的最小值
本题子问题的分析(状态转移)是十分清晰的,因为每一次要么从第一个序列中取元素f(i-1,j),要么从第二个序列中取元素f(i,j-1),但是每一个的L(c)都显得难以计算,因为难以记录选出的元素是否在新的序列当中出现过,或者出现过却不知道出现的位置。按照紫书的分析,不应该直接去算L(c),而是按次累加那些已经开始但尚未结束的颜色种数,所以预处理算出c[i][j]即第一个序列中选i个,第二个序列中选j个时两个序列中已经出现但是没有结束的颜色总数,然后在dp时累加即可。
注意不用滚动会TLE哦~
#include<cstdio> #include<cstdlib> #include<cctype> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<iostream> #define maxn 5005 #define inf maxn*maxn using namespace std; char a[maxn],b[maxn]; int n,m,T; int f[2][maxn]; int sp[30],sq[30],ep[30],eq[30];//记录每一个字母在第一个序列和第二个序列的起始和结束位置 int c[maxn][maxn];//表示第一个序列用了i个字母,第二个序列用了j个字母时已经开始但未结束的颜色数目 /* f(i,j)表示把a[i]...a 和b[j]...b[m]合并成一个序列后最小的LC 填表前 f(i,j)=0 f(i,j)=f(i-1,j)+c[i-1][j] if(j==0) f(i,j)=f(i,j-1)+c[i][j-1] if(i==0) f(i,j)=min(f(i,j-1)+c[i][j-1],f(i-1,j)+c[i-1][j]) else Ans=f(n,m); */ void ready() { for(int i=1;i<=n;i++)a[i]=a[i]-'A'; for(int j=1;j<=m;j++)b[j]=b[j]-'A'; for(int i=0;i<26;i++) sp[i]=sq[i]=inf; for(int i=1;i<=n;i++) { sp[a[i]]=min(sp[a[i]],i); ep[a[i]]=i; } for(int j=1;j<=m;j++) { sq[b[j]]=min(sq[b[j]],j); eq[b[j]]=j; } for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) { int t=0; for(int k=0;k<26;k++) if((i>=sp[k] || j>=sq[k]) && (i<ep[k] || j<eq[k])) t++; c[i][j]=t; } } void dp() { ready(); memset(f,0,sizeof(f)); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) { if(i==0 && j==0)continue;//边界 else if(i==0)f[i%2][j]=f[i%2][j-1]+c[0][j]; else if(j==0)f[i%2][j]=f[(i-1)%2][j]+c[i][0]; else f[i%2][j]=min(f[(i-1)%2][j],f[i%2][j-1])+c[i][j]; } printf("%d",f[n%2][m]); } int main() { //freopen("color.in","r",stdin); //freopen("color.out","w",stdout); scanf("%d",&T); while(T--) { scanf("%s%s",a+1,b+1); n=strlen(a+1); m=strlen(b+1); dp(); } return 0; }
相关文章推荐
- 颜色的长度(uva 1625)
- UVA 1625 Color Length 颜色的长度 (预处理+dp)
- 动态规划(颜色的长度,uva 1625)
- UVa 1625 颜色的长度
- UVA1625颜色的长度
- Uva 1625,颜色的长度
- [UVa1625]颜色的长度
- UVa - 1625 Color Length 颜色的长度 动态规划 重庆一中高2018级竞赛班第十次测试 2016.9.16 Problem 2
- uva1625 颜色的长度
- UVA1625 颜色的长度(color length)(重庆一中高2018级信息学竞赛测验10) 解题报告
- Uva1625 -Color Length(DP)
- 找出第二个文本抄袭第一个文本的所有位置和长度 后缀数组 UVA 10526 - Intellectual Property
- UVA 1625 - Color Length【DP】
- 【UVa 10003】【区间DP】Cutting Sticks【有一个长为L的木棍,木棍中间有n个切点。每次切割的费用为当前木棍的长度。求切割木棍的最小费用。】
- UVa 1625 color length--dp状态转移的巧妙计算
- UVa1625 - Color Length
- UVA1593 不定量不定长度单词,左对齐
- UVa 1625 Color Length
- 《CSS权威指南》学习记录——颜色和长度单位
- 仿邮箱密码色条,随除长度变换颜色