【DP模型:LCS】uva1625 Color Length
2015-07-22 09:00
387 查看
题目描述:对给定的两个长度为n和m的颜色序列,将他们合并,即每次把序列的开头放入新的序列的尾部。计每种颜色的跨度为序列中最大位置与最小位置之差。求最小跨度。
数据范围:n,m<=5000
这道题很容易想到LCS(最长公共子序列)。然而并没有什么用= =
一开始我想的状态转移方程式:
f[i][j]=max(f[i-1][j]+add(a[i]),f[i][j-1]+add(b[j])) //a,b为两个颜色序列 add表示放入某元素增加的跨度
发现add()并不好算= =
看大神的方法:采用倒推。
令f(i,j)表示两个串的下标移动至i,j时,还要产生的最小跨度。
方程式:f(i,j)=min(f(i,j+1),f(i+1,j))+add(i,j)
初始化:f(lena,lenb)=0
其中add(i,j)怎么算?
计b1[i]为i在第一个序列开始位置,b2[i]为i在第二个序列开始位置
e1[i]为i在第一个序列结束位置,e2[i]为i在第二个序列结束位置
若i已经出现完了,就不再增加跨度。若i还未出现,也不再增加跨度。其余情况均增加跨度。(具体操作见代码)
目标:f(0,0)
在实现过程中注意细节。
本题思维难度适中。然而我并没有想出来= = 说明逆向思维不够= =
蒟蒻加油 ↖(^ω^)↗
数据范围:n,m<=5000
这道题很容易想到LCS(最长公共子序列)。然而并没有什么用= =
一开始我想的状态转移方程式:
f[i][j]=max(f[i-1][j]+add(a[i]),f[i][j-1]+add(b[j])) //a,b为两个颜色序列 add表示放入某元素增加的跨度
发现add()并不好算= =
看大神的方法:采用倒推。
令f(i,j)表示两个串的下标移动至i,j时,还要产生的最小跨度。
方程式:f(i,j)=min(f(i,j+1),f(i+1,j))+add(i,j)
初始化:f(lena,lenb)=0
其中add(i,j)怎么算?
计b1[i]为i在第一个序列开始位置,b2[i]为i在第二个序列开始位置
e1[i]为i在第一个序列结束位置,e2[i]为i在第二个序列结束位置
若i已经出现完了,就不再增加跨度。若i还未出现,也不再增加跨度。其余情况均增加跨度。(具体操作见代码)
目标:f(0,0)
在实现过程中注意细节。
本题思维难度适中。然而我并没有想出来= = 说明逆向思维不够= =
蒟蒻加油 ↖(^ω^)↗
#include <iostream> #include <cstdio> #include <cstring> #define min(a,b) ((a)<(b)?(a):(b)) #define MAXN 5005 using namespace std; int len1 ,len2 ,b1[27] ,b2[27] ,e1[27] ,e2[27] ; int f[MAXN][MAXN] ; char c1[MAXN] ,c2[MAXN] ; int add(int a,int b) { --a,--b; int cnt=0; for(int i=0;i<26;++i) { if(e1[i]<=a&&e2[i]<=b)continue; if(b1[i]>a&&b2[i]>b||b1[i]>a&&b2[i]==-1||b2[i]>b&&b1[i]==-1)continue; ++cnt; } return cnt; } int main() { int T; scanf("%d",&T); while(T--) { memset(b1,-1,sizeof(b1)); memset(b2,-1,sizeof(b2)); memset(e1,-1,sizeof(e1)); memset(e2,-1,sizeof(e2)); scanf("%s%s",c1,c2); len1=strlen(c1),len2=strlen(c2); for(int i=0;i<len1;++i) { c1[i]-='A'; if(b1[c1[i]]==-1) b1[c1[i]]=i; e1[c1[i]]=i; } for(int i=0;i<len2;++i) { c2[i]-='A'; if(b2[c2[i]]==-1) b2[c2[i]]=i; e2[c2[i]]=i; } f[len1][len2]=0; for(int i=len2-1;i>=0;--i) f[len1][i]=f[len1][i+1]+add(len1,i); for(int i=len1-1;i>=0;--i) { f[i][len2]=f[i+1][len2]+add(i,len2); for(int j=len2-1;j>=0;--j) f[i][j]=min(f[i][j+1],f[i+1][j])+add(i,j); } printf("%d\n",f[0][0]); } return 0; }
相关文章推荐
- Java数组简单用法
- iOS开发 - CALayer图层
- 常用的 nosql 数据库
- [leetcode 189] Rotate Array
- 图片折叠效果:Layer的contentsRect属性和渐变层
- google ip 系列之一
- iOS接收null的处理方法
- G - Gargari and Bishops-贪心暴力
- iOS应用安全开发,你不知道的那些事
- visual studio 2015 下载地址
- 深入理解Java内存模型--转载
- 11个Visual Studio代码性能分析工具
- virtualbox_ubuntu和Windows共享文件夹
- 安卓中的JSON解析
- Linux中出现/usr/bin/ld: cannot find -lxxx报错该怎么办?
- HDOJ_Problem Archive_1000_A + B Problem
- H - 24 Game
- 7/21 A 解题报告
- hdu5289(2015多校1)--Assignment(单调队列)
- url注意事项