UVA - 1625 Color Length[序列DP 提前计算代价]

时间:2023-02-17 12:48:16
UVA - 1625
UVA - 1625 Color Length[序列DP 提前计算代价]
 

白书
很明显f[i][j]表示第一个取到i第二个取到j的代价
问题在于代价的计算,并不知道每种颜色的开始和结束
 
和模拟赛那道环形DP很想,计算这次转移会给其他的元素带来的代价,也就是转移前已经出现但还没结束的元素都会代价+1
 
预处理每种颜色在两个序列中出现的位置bg[i][0/1]和ed[i][0/1],
计算f[i][j]时同时计算w[i][j]为(i,j)这个状态已经出现还没结束的个数
注意bg要先初始化为INF,计算w:
if(bg[c][0]==i&&bg[c][1]>j) w[i][j]++;
if(ed[c][0]==i&&ed[c][1]<=j) w[i][j]--;
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
const int N=,INF=1e9;
int T,n,m;
char a[N],b[N];
int f[N][N],w[N][N],bg[][],ed[][];
void dp(){
memset(bg,,sizeof(bg));
memset(ed,,sizeof(ed));
for(int i=;i<;i++) bg[i][]=bg[i][]=INF;
for(int i=;i<=n;i++){
int c=a[i]-'A';
if(bg[c][]==INF) bg[c][]=i;
ed[c][]=i;
}
for(int i=;i<=m;i++){
int c=b[i]-'A';
if(bg[c][]==INF) bg[c][]=i;
ed[c][]=i;
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
//f[i][j]=min(f[i-1][j]+cal(i-1,j),f[i][j-1]+cal(i,j-1));
//f[i][j]=min(f[i-1][j],f[i][j-1])+cal(i,j);
if(i==&&j==) continue;
int t1=INF,t2=INF;
if(i>) t1=f[i-][j]+w[i-][j];
if(j>) t2=f[i][j-]+w[i][j-];
f[i][j]=min(t1,t2); if(i>){
w[i][j]=w[i-][j];
int c=a[i]-'A';
if(bg[c][]==i&&bg[c][]>j) w[i][j]++;
if(ed[c][]==i&&ed[c][]<=j) w[i][j]--;
}else{
w[i][j]=w[i][j-];
int c=b[j]-'A';
if(bg[c][]==j&&bg[c][]>i) w[i][j]++;
if(ed[c][]==j&&ed[c][]<=i) w[i][j]--;
//if(b[j]=='R') printf("R %d %d %d %d\n",bg[c][1],ed[c][1],i,j);
}
//printf("%d %d %d %d\n",i,j,f[i][j],w[i][j]);
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%s%s",a+,b+);
n=strlen(a+);m=strlen(b+);
dp();
printf("%d\n",f[n][m]);
}
}

白书的标程用了滚动数组,可以借鉴一下

// UVa1625 Color Length
// Rujia Liu
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn = + ;
const int INF = ; char p[maxn], q[maxn]; // starts from position 1
int sp[], sq[], ep[], eq[]; // sp[i] start positions of character i in p
int d[][maxn], c[][maxn]; // 滚动数组 c[i][j]: how many "incomplete" colors in the mixed sequence int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s%s", p+, q+); int n = strlen(p+);
int m = strlen(q+);
for(int i = ; i <= n; i++) p[i] -= 'A';
for(int i = ; i <= m; i++) q[i] -= 'A'; // calculate s and e
for(int i = ; i < ; i++)
{
sp[i] = sq[i] = INF;
ep[i] = eq[i] = ;
}
for(int i = ; i <= n; i++)
{
sp[p[i]] = min(sp[p[i]], i);
ep[p[i]] = i;
}
for(int i = ; i <= m; i++)
{
sq[q[i]] = min(sq[q[i]], i);
eq[q[i]] = i;
} // dp
int t = ;
memset(c, , sizeof(c));
memset(d, , sizeof(d));
for(int i = ; i <= n; i++)
{
for(int j = ; j <= m; j++)
{
if(!i && !j) continue; // calculate d
int v1 = INF, v2 = INF;
//计算d[i][j], d[i][j]由d[i-1][j]或d[i][j-1]添加一个字母得到
if(i) v1 = d[t^][j] + c[t^][j]; // remove from p
if(j) v2 = d[t][j - ] + c[t][j - ]; // remove from q
d[t][j] = min(v1, v2); // calculate c
if(i)
{
c[t][j] = c[t^][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 - ];
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 ^= ;
}
printf("%d\n", d[t^][m]);
}
return ;
}

UVA - 1625 Color Length[序列DP 提前计算代价]的更多相关文章

  1. UVA - 1625 Color Length&lbrack;序列DP 代价计算技巧&rsqb;

    UVA - 1625 Color Length   白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束   和模拟赛那道环形DP很想,计算这 ...

  2. UVa 1625 - Color Length(线性DP &plus; 滚动数组)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. UVa 1625 Color Length &lpar;DP&rpar;

    题意:给定两个序列,让你组成一个新的序列,让两个相同字符的位置最大差之和最小.组成方式只能从一个序列前部拿出一个字符放到新序列中. 析:这个题状态表示和转移很容易想到,主要是在处理上面,dp[i][j ...

  4. UVA 1625 Color Length 颜色的长度 (预处理&plus;dp)

    dp[i][j]表示前一个序列拿了i个颜色,后一个序列拿了j个颜色的最小花费. 转移的时候显然只能向dp[i+1][j],或dp[i][j+1]转移,每增加拿走一个颜色,之前已经出现但没结束的颜色个数 ...

  5. UVA 1625 &quot&semi;Color Length&quot&semi; (基础DP)

    传送门 •参考资料 [1]:HopeForBetter •题意 •题解(by 紫书) •我的理解 用了一上午的时间,参考紫书+上述博文,终于解决了疑惑: 定义第一个颜色序列用串 s 表示,第二个用串 ...

  6. UVa 1625 Color Length

    思路还算明白,不过要落实到代码上还真敲不出来. 题意: 有两个由大写字母组成的颜色序列,将它们合并成一个序列:每次可以把其中一个序列开头的颜色放到新序列的尾部. 对于每种颜色,其跨度定义为合并后的序列 ...

  7. 洛谷P1220关路灯&lbrack;区间DP 提前计算代价&rsqb;

    题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯. 为了给村 ...

  8. BZOJ 2726&colon; &lbrack;SDOI2012&rsqb;任务安排 &lbrack;斜率优化DP 二分 提前计算代价&rsqb;

    2726: [SDOI2012]任务安排 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 868  Solved: 236[Submit][Status ...

  9. 1625 - Color Length——&lbrack;动态规划&rsqb;

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

随机推荐

  1. C&num;简单的对象交互

    在对象的世界里,一切皆为对象;对象与对象相互独立,互不干涉,但在一定外力的作用下对象开始共同努力 对象交互的实例 电视机大家都有吧,依照万物皆对象的思维模式来看,电视机可以是一个类,然后电视机有一些基 ...

  2. Windows Phone App的dump文件实例分析-Stack Overflow

    前言 这篇文章我们一起来分析一个从Windows Phone Dev Center上下载下来的dump file.首先按照我上一篇的步骤设置好我们的Windbg,并按住Ctrl +D打开dumpfil ...

  3. hdu3535 背包大杂汇

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3535 //不想写题解,这道题让我对背包的理解更深了,我相信我不会忘记的.... 代码: # ...

  4. spring 第一篇(1-1):让java开发变得更简单&lpar;下&rpar;转

    spring 第一篇(1-1):让java开发变得更简单(下) 这个波主虽然只发了几篇,但是写的很好 上面一篇文章写的很好,其中提及到了Spring的jdbcTemplate,templet方式我之前 ...

  5. linux内核下载

    01最新版:https://www.kernel.org/ 02老旧版:https://www.kernel.org/pub/linux/kernel/v3.x/ ------------------ ...

  6. 对于Linux和windows的个人的看法

    对于这两个系统,我和众多朋友一样的纠结.接触Linux是从大二就开始的,后来在某机构学习该系统服务器的配置,当时使用的是红帽子9. 经过这么多年的感悟,做过多系统,也用来装过虚拟机,搭建过网络.曾经为 ...

  7. android图像模糊技术

    今天我们来更深入了解一下Android开发上的模糊技术.我读过几篇有关的文章,也在*上看过一些相关教程的帖子,所以我想在这里总结一下学到的东西. 为什么学习这个模糊技术? 现在 ...

  8. jquery &plus; ajax调用后台方法

    前台js: var parameter = ""; $.ajax({ type: "POST", //提交方式 url: "Default.aspx/ ...

  9. JavaScript数据结构与算法&lpar;四&rpar; 循环队列的实现

    实现击鼓传花,需要用到上一章所述队列类Queue TypeScript方式实现源码 let hotPotato = (nameList, num) => { let queue = new Qu ...

  10. JAVA高级-面试题总结

    最近面试了一些公司,针对面试中遇到的问题在此记录,提升自己,造福大家 一.java源码相关 ArrayList创建和add等各种api使用原理 HashMap 的创建,put原理,和HashTable ...