1625 - Color Length——[动态规划]
2016-05-21 15:58
330 查看
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4500
题目分析:
本题要将两条路上的车辆混合成一路,混合方法可以是:每次将一个颜色序列中的开头颜色放入新序列的尾部。可以定义状态d[i][j]为第一个序列移走了i辆车,第2个序列移走了j辆车时,新序列的颜色长度。如何进行状态转移呢?
假设第一个序列为A
,第二个序列为B[m],C[i][j]表示由A中前i个元素和B中前j个元素组成的最优新序列。下面我们考虑将颜色A[i]加入C[i-1][j]的情况。组成新序列的颜色可以分成两类:(1)已经出现还未结束的颜色 (2)已经结束的颜色 ,设第(1)类元素个数为s,那么将A[i]加入后,每个还未结束的颜色长度均要增加1,所以总长度为 d[i-1][j]+s。 这样我们就得到了状态转移方程 d[i][j]=min{d[i-1][j]+s1,d[i][j-1]+s2} ,s1为将A[i]加入C[i-1][j]的总长度增量,s2为将B[j]加入C[i][j-1]的总长度增量。
那么主要问题就转换成了如何计算C[i][j]中一景出现还未结束的颜色个数,可以对原先的两个序列预处理一遍,很容易在O(n*m)时间内计算出每个颜色开始和结束的位置。总时间复杂度为O(n*m)。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=100;//5000; int d[maxn+5][maxn+5]; int b[2][26]; int e[2][26]; int L[26]; char s1[maxn+5]; char s2[maxn+5]; int n,m; void init(){ memset(L, 0, sizeof L); memset(b, 0, sizeof b); memset(e, 0, sizeof e); } void pre_process(){ for(int i=0;i<n;i++){ char ch=s1[i]; int id=ch-'A'; if(b[0][id]==0){ b[0][id]=i+1; } } for(int i=n-1;i>=0;i--){ char ch=s1[i]; int id=ch-'A'; if(e[0][id]==0){ e[0][id]=i+1; } } for(int i=0;i<m;i++){ char ch=s2[i]; int id=ch-'A'; if(b[1][id]==0){ b[1][id]=i+1; } } for(int i=m-1;i>=0;i--){ char ch=s2[i]; int id=ch-'A'; if(e[1][id]==0){ e[1][id]=i+1; } } } int sum(int i,int j,int flag){ int ans=0; if(flag==0){ for(int k=0;k<26;k++) { if(((b[0][k]>0&&b[0][k]<=i-1)||(b[1][k]>0&&b[1][k]<=j))&&((e[0][k]>0&&e[0][k]>i-1)||(e[1][k]>0&&e[1][k]>j))) ans++; } } else { for(int k=0;k<26;k++) { if(((b[0][k]>0&&b[0][k]<=i)||(b[1][k]>0&&b[1][k]<=j-1))&&((e[0][k]>0&&e[0][k]>i)||(e[1][k]>0&&e[1][k]>j-1))) ans++; } } return ans; } int main(int argc, const char * argv[]) { int T; scanf("%d",&T); while(T--){ scanf("%s%s",s1,s2); n=strlen(s1); m=strlen(s2); init(); pre_process(); d[0][0]=0; for(int i=1;i<=n;i++) d[i][0]=d[i-1][0]+sum(i,0,0); for(int j=1;j<=m;j++) d[0][j]=d[0][j-1]+sum(0,j,1); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ d[i][j]=min(d[i-1][j]+sum(i,j,0),d[i][j-1]+sum(i,j,1)); } } printf("%d\n",d [m]); } return 0; }
相关文章推荐
- ZOJ1119(SPF)
- 学习练习 java 实例属性 静态属性
- 文件上传工具类(重命名,以及判断类型)
- phpjm解密程序,也适用于其他混淆加密的破解
- CSS float浮动的深入研究、详解及拓展(二)
- C++图像处理中从硬盘读入图像文件,并将相应数据赋值给图像类的char**data成员
- Java线程池使用说明
- Class文件结构
- 软键盘挤压布局的问题
- 字符串测试题1
- maven出错The folder is already a source folder
- css样式问题,table中的td值撑开了,样式变了
- mysql 安装 和 配置 在 centos 7
- POJ-1287-Networking(最小生成树 普利姆)
- 移动开发内存分类
- new和delete 基类指针指向继承类的对象时,delete的过程
- c++实现矩阵的余弦相似度
- 学习练习 java面向对象封装汽车
- IIS配置
- Axure 实现数字自动加键功能(点击“+”数字加1,点击“-”数字减1)