例题9-8 颜色的长度 UVa1625
来源:互联网 发布:Servlet接收json gson 编辑:程序博客网 时间:2024/06/05 04:03
1.题目描述:点击打开链接
2.解题思路:本题利用区间dp解决,但是本题是一道比较复杂的区间dp,做法不太容易理解,需要慢慢分析。首先,题目要求我们寻找一种合并的方式,使得最后的总代价最小,这里的总代价就是题目中所说的不同字母的L(i)值的和。然而本题不能按照以往的经验,把两个序列分别已经移动走了i和j个元素,还需要多少代价作为状态,因为这样的定义并不知道某个字符什么时候会结束,而当字符结束时候,又不记得它是什么时候第一次出现的。
本题正确的状态定义是:第一个序列移走i个元素和第二个序列移走j个元素时的最小代价。为了防止出现不知道字符何时开始以及何时结束的情况,我们需要进行一番预处理。用p,q分别表示两个字符串,sp[c],ep[c]表示在字符串p中,c字符第一次出现的下标和最后一次出现的下标。同样的可以定义sq[c],eq[c]。为了便于计算状态转移时候新增的代价,我们来考虑新增的代价来自哪里。根据题意,如果某个字符没有结束,那么新增加一个字符后,所有没有结束的字符的距离都要+1,这就提示我们,可以设置一个数组c[i][j],表示从p字符串移动i个字符,q字符串移动j个字符后,已经开始但是没有结束的字符的个数。这样,可以得到如下的状态转移方程:
dp(i,j)=min(dp(i-1,j)+c[i-1][j],dp(i,j-1)+c[i][j-1]);
因此,接下来的问题转化为如何计算c[i][j]?显然,c[i][j]的计算要根据d[i][j]的情况而变化,而且要用到之前设置的sp,sq,ep,eq数组。假设新的字符c来自p字符串,那么,首先令c[i][j]=c[i-1][j],如果这个字符c是首次出现的,即sp[c]==i且sq[c]>j,那么c[i][j]++,否则,如果c的加入意味着c字符从此结束,即ep[c]==i且eq[c]<=j,那么之后的c[i][j]就不能算入c字符了,所以c[i][j]--。如果新的字符c来自q字符串,依然可以同上处理。这样就完成了c[i][j]的计算。而且每次都要先更新d[i][j],再更新c[i][j]。
可见,所有的状态一共有O(NM)种,且状态转移只需要O(1)的时间,因此本题的时间复杂度是O(NM)。下面的代码利用了滚动数组优化。
3.代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<functional>using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)typedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, int> P;const int N=5000+10;const int INF=100000000;char p[N],q[N];int sp[26],sq[26],ep[26],eq[26];int d[2][N],c[2][N];int main(){ int T; scanf("%d",&T); while(T--) { scanf("%s%s",p+1,q+1); //下标从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'; rep(i,26){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); //预处理第i个字符在p字符串的第一次出现的位置和最后出现的位置 ep[p[i]]=i; } for(int i=1;i<=m;i++) { sq[q[i]]=min(sq[q[i]],i); //同上 eq[q[i]]=i; } int t=0; me(c);me(d); rep(i,n+1) { rep(j,m+1) { 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); //以下根据新字符来自p数组还是q数组更新c[i][j] 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; //注意:一定要在j跑完一轮后再更新t } printf("%d\n",d[t^1][m]); //由于i==n结束时又执行了一次t^=1,因此答案是d[t^1][m] }}
- 例题9-8 颜色的长度 UVa1625
- uva1625 颜色的长度
- 【UVa1625】颜色的长度
- [UVa1625]颜色的长度
- UVA1625颜色的长度
- #UVA1625#Color Length--颜色的长度(DP + 提前累加思想)
- UVA1625 颜色的长度(color length)(重庆一中高2018级信息学竞赛测验10) 解题报告
- UVa1625
- uva1625
- UVa1625
- 动态规划_线性结构例题_Color Length(UVA1625)
- CSS的颜色和长度
- 比较经典的位字段例题(颜色三原色)
- Swift String to UIColor (支持3,4,6,8长度的16进制颜色值)
- 紫书动规 例题9-8 UVA
- 颜色值、长度值
- 前端常用到的颜色值和长度值设置
- 动态规划(颜色的长度,uva 1625)
- HTTP协议
- 微信恢复工具 MMRecovery 犹如一朵青莲
- 深度学习-theano-windows -cuda-环境搭建
- 浅谈Java中的hashcode方法
- HDU 1036.Average is not Fast Enough!【精度及格式控制】【8月23】
- 例题9-8 颜色的长度 UVa1625
- HDU 4709 Herding(叉乘法)
- 【C++数据结构】顺序表的模版类实现
- setup subline text3
- JS的HTML DOM disabled 属性
- 1-2、自定义Partitioner代码
- 虚拟机与docker
- 【ACM】华为oj--合法ip
- iOS项目开发实战——学会使用TableView列表控件(一)