题意:现给定一个字符集中一共Z个元素的环境,给出一个Z*Z的数组,表示从i到j之间的距离。给定两组字符串,分别问包含着两个字符串(给定的字符串为所求字符串的子序列不是子串)对应位的距离和值最小为多少?输出这两个字符串。

分析:该题的状态还是比较好开设的,设dp[i][j]表示a串的前i个字符和b串的前j个字符被包含后的最小开销,于是动态转移方程:

dp[i][j] = min(dp[i][j], dp[i-1][j] + wa[sa[i]]);  其中wa数组表示某个字符与另外一个最小花费的字符匹配,sa[i]表示a串的第i个字符
dp[i][j] = min(dp[i][j], dp[i][j-1] + wb[sb[j]]);  意义同上一个转移类似,均表示一个字符与一个最便宜的字符匹配
dp[i][j] = min(dp[i][j], dp[i-1][j-1] + dist[sa[i]][sb[j]]);  该方程的意义为两个串均拿出一个字符来匹配

这里需要说明的是补全两个串的最长长度最多为两个串长度之和,由上面的转移可以知道,每个位至少会有一个字符是属于串a或者是串b。

还有一个地方要特别注意的是,给定字符集可能会有超过127的ascii码,并且编号之后可能有编号大于127,因此前面自己写的sa[i] = mp[sa[i]]一直RE就是出现了负数,改成了unsigned char了。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <map>
using namespace std; const int Z = ;
const int N = ;
int d[Z][Z];
map<char, int>mp;
unsigned char str[Z], sa[N], sb[N];
int na[N], nb[N];
int la, lb, wa[Z], wb[Z], ca[Z], cb[Z];
int idxa, idxb, dp[N][N], path[N][N];
char qa[N<<], qb[N<<];
// wa、wb数组分别用来说明sa串中的某字符的最佳匹配和sb串中某字符的最佳匹配
// ca、cb数组记录在wa、wb数组取得最优解的情况下所对应的字符 void dfs(int i, int j) {
if (!i && !j) return;
if (i > && j > && dp[i][j] == dp[i-][j-] + d[sa[i]][sb[j]]) {
qa[idxa++] = str[sa[i]];
qb[idxb++] = str[sb[j]];
dfs(i-, j-);
} else if (i > && dp[i][j] == dp[i-][j] + wa[sa[i]]){
qa[idxa++] = str[sa[i]];
qb[idxb++] = str[ca[sa[i]]];
dfs(i-, j);
} else {
qa[idxa++] = str[cb[sb[j]]];
qb[idxb++] = str[sb[j]];
dfs(i, j-);
}
} void gao() {
// 最坏情况需要构造出长度为la+lb长度的串
memset(dp, 0x3f, sizeof (dp));
dp[][] = ;
for (int i = ; i <= la; ++i) {
for (int j = ; j <= lb; ++j) {
if (i > ) {
dp[i][j] = min(dp[i][j], dp[i-][j] + wa[sa[i]]);
}
if (j > ) {
dp[i][j] = min(dp[i][j], dp[i][j-] + wb[sb[j]]);
}
if (i > && j > ) {
dp[i][j] = min(dp[i][j], dp[i-][j-] + d[sa[i]][sb[j]]);
}
}
}
printf("%d\n", dp[la][lb]);
idxa = idxb = ;
dfs(la, lb);
for (int i = idxa-; i >= ; --i) {
putchar(qa[i]);
}
puts("");
for (int i = idxb-; i >= ; --i) {
putchar(qb[i]);
}
puts("");
} int main() {
int T;
scanf("%d%", &T);
while (T--) {
mp.clear();
memset(wa, 0x3f, sizeof (wa));
memset(wb, 0x3f, sizeof (wb));
scanf("%s", str+);
int len = strlen((char*)(str+));
for (int i = ; i <= len; ++i) {
mp[str[i]] = i;
}
scanf("%s %s", sa+, sb+);
la = strlen((char *)(sa+)), lb = strlen((char *)(sb+));
for (int i = ; i <= la; ++i) {
sa[i] = mp[sa[i]];
}
for (int i = ; i <= lb; ++i) {
sb[i] = mp[sb[i]];
}
for (int i = ; i <= len; ++i) {
for (int j = ; j <= len; ++j) {
scanf("%d", &d[i][j]);
if (wa[i] > d[i][j]) {
wa[i] = d[i][j], ca[i] = j;
}
if (wb[j] > d[i][j]) {
wb[j] = d[i][j], cb[j] = i;
}
}
}
gao();
}
return ;
}

ZOJ-2366 Weird Dissimilarity 动态规划+贪心的更多相关文章

  1. hdu 1257 最少拦截系统(动态规划 / 贪心)

    最少拦截系统 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  2. 洛谷P1095守望者的逃离题解-伪动态规划/贪心

    链接 题目描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上.为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很 ...

  3. 二叉树遍历问题、时间空间复杂度、淘汰策略算法、lru数据结构、动态规划贪心算法

    二叉树的前序遍历.中序遍历.后序遍历 前序遍历 遍历顺序规则为[根左右] ABCDEFGHK 中序遍历 遍历顺序规则为[左根右] BDCAEHGKF 后序遍历 遍历顺序规则为[左右根] DCBHKGF ...

  4. ZOJ 3699 Dakar Rally(贪心)

    这是一道贪心题,他的贪心思想很容易想明白,我们保证油箱里的油始终是最便宜的我们最后的花费就能是最少的.实现方法就是:比如现在在i点,我们看邮箱满载能最远到达哪里,不妨设最远到达j,(j >= i ...

  5. ZOJ 2002 Copying Books 二分 贪心

    传送门:Zoj2002 题目大意:从左到右把一排数字k分,得到最小化最大份,如果有多组解,左边的尽量小. 思路:贪心+二分(参考青蛙过河). 方向:从右向左. 注意:有可能最小化时不够k分.如     ...

  6. CF1088F Ehab and a weird weight formula 贪心 倍增

    CF1088F Ehab and a weird weight formula 题意 给定一棵树,点有点权,其中这棵树满足除了权值最小的点外,每个点至少有一个点权小于它的相邻点. 要求你重新构建这棵树 ...

  7. [ZOJ 3662] Math Magic (动态规划+状态压缩)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3662 之前写过这道题,结果被康神吐槽说代码写的挫. 的确,那时候 ...

  8. ZOJ 3941 Kpop Music Party 贪心

    题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3941 题解: 先吧所给的区间合并,得到若干个独立的区间. 然后从左 ...

  9. ZOJ 3607 Lazier Salesgirl(贪心)

    题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3607 题意:一个卖面包的小姑娘,给第i个来买面包的人的价格是pi, ...

随机推荐

  1. Linux系统的中断、系统调用和调度概述【转】

    转自:http://blog.csdn.net/yanlinwang/article/details/8169725 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近学习Linux操作系统, ...

  2. Java中的TreeMap、Comparable、Comparator

    我们知道HashMap的存储位置是按照key这个对象的hashCode来存放的,而TreeMap则是不是按照hashCode来存放,他是按照实现的Comparable接口的compareTo这个方法来 ...

  3. php单例模式是怎么实现的呢

    <?php /** * 设计模式之单例模式 * $_instance必须声明为静态的私有变量 * 构造函数和析构函数必须声明为私有,防止外部程序new * 类从而失去单例模式的意义 * getI ...

  4. Python升级Yum不能使用解决

    1.系统版本 [root@vm10-254-206-95 ~]# cat /etc/issue CentOS release 6.4 (Final) Kernel \r on an \m 2.系统默认 ...

  5. 微信支付 APP 支付方式的服务器端处理程序

    对于微信的APP的支付,客户服务说只能通过微信开放平台申请.后来在公众帐号确实发现了证据:  微信支付在申请的时候就比较严(麻烦),对服务类的一些支付,本来商品就是虚拟的,所以需要将商品描述的比较详细 ...

  6. android 代码整体回退

    repo forall -c 'HAHA=`git log --before="3 days" -1 --pretty=format:"%H"`;git res ...

  7. HDU 自动刷题机 Auto AC (轻轻松松进入HDU首页)

    前言: 在写这篇文章之前,首先感谢给我思路以及帮助过我的学长们 以下4篇博客都是学长原创,其中有很多有用的,值得学习的东西,希望能够帮到大家! 1.手把手教你用C++ 写ACM自动刷题神器(冲入HDU ...

  8. 跟我一起Django - 01 安装和初始化

    跟我一起Django - 01 安装和初始化 python环境 C:\Python27\Lib\site-packages>python --versionPython 2.7.5 安装setu ...

  9. 转载-python学习笔记之输入输出功能读取和写入数据

    读取.写入和 Python 在 “探索 Python” 系列以前的文章中,学习了基本的 Python 数据类型和一些容器数据类型,例如tuple.string 和 list.其他文章讨论了 Pytho ...

  10. #ifdef DEBUG的理解

    今天看到一段代码,对ifdef的概念比较模糊,于是去学习了一下,找到一个很好的解释,如下: 在工程设置里有一些设置会对该工程自动产生一系列的宏,用以控制程序的编译和运行.就好象楼上说的一样,如果你把代 ...