题意:现给定一个字符集中一共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 = 256;
const int N = 2005;
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<<1], qb[N<<1];
// wa、wb数组分别用来说明sa串中的某字符的最佳匹配和sb串中某字符的最佳匹配
// ca、cb数组记录在wa、wb数组取得最优解的情况下所对应的字符 void dfs(int i, int j) {if (!i && !j) return;if (i > 0 && j > 0 && dp[i][j] == dp[i-1][j-1] + d[sa[i]][sb[j]]) {qa[idxa++] = str[sa[i]];qb[idxb++] = str[sb[j]];dfs(i-1, j-1);} else if (i > 0 && dp[i][j] == dp[i-1][j] + wa[sa[i]]){qa[idxa++] = str[sa[i]];qb[idxb++] = str[ca[sa[i]]];dfs(i-1, j);} else {qa[idxa++] = str[cb[sb[j]]];qb[idxb++] = str[sb[j]];dfs(i, j-1);}
}void gao() {// 最坏情况需要构造出长度为la+lb长度的串memset(dp, 0x3f, sizeof (dp));dp[0][0] = 0;for (int i = 0; i <= la; ++i) {for (int j = 0; j <= lb; ++j) {if (i > 0) {dp[i][j] = min(dp[i][j], dp[i-1][j] + wa[sa[i]]);}if (j > 0) {dp[i][j] = min(dp[i][j], dp[i][j-1] + wb[sb[j]]);}if (i > 0 && j > 0) {dp[i][j] = min(dp[i][j], dp[i-1][j-1] + d[sa[i]][sb[j]]);}}}printf("%d\n", dp[la][lb]);idxa = idxb = 0;dfs(la, lb);for (int i = idxa-1; i >= 0; --i) {putchar(qa[i]);}puts("");for (int i = idxb-1; i >= 0; --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+1);int len = strlen((char*)(str+1));for (int i = 1; i <= len; ++i) {mp[str[i]] = i;}scanf("%s %s", sa+1, sb+1);la = strlen((char *)(sa+1)), lb = strlen((char *)(sb+1));for (int i = 1; i <= la; ++i) {sa[i] = mp[sa[i]];}for (int i = 1; i <= lb; ++i) {sb[i] = mp[sb[i]];}for (int i = 1; i <= len; ++i) {for (int j = 1; 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 0;
}

转载于:https://www.cnblogs.com/Lyush/p/3206645.html

ZOJ-2366 Weird Dissimilarity 动态规划+贪心相关推荐

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

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

  2. 动态规划/贪心 - 无重叠区间

    动态规划 dp[i]dp[i]dp[i]表示以区间iii结尾,可以共存最多的区间数量. dp[i]=max(dp[i],dp[j]+1)dp[i] = max(dp[i], dp[j] + 1)dp[ ...

  3. [剑指offer]面试题第[42]题[Leedcode][JAVA][第53题][最大子序和][动态规划][贪心][分治]

    [问题描述][第53题][最大子序和][中等] 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和.示例:输入: [-2,1,-3,4,-1,2,1, ...

  4. LeetCode 1024. 视频拼接(动态规划/贪心)

    文章目录 1. 题目 2. 解题 2.1 动态规划 2.2 贪心 1. 题目 你将会获得一系列视频片段,这些片段来自于一项持续时长为 T 秒的体育赛事.这些片段可能有所重叠,也可能长度不一. 视频片段 ...

  5. [LeetCode刷题笔记]714 - 买卖股票的最佳时机含手续费(C++/Python3/Java/动态规划/贪心)

    一.题目描述 给定一个整数数组 prices 和 整数 fee ,其中 prices[i] 表示第 i 天的股票价格,fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每笔交易都需要付 ...

  6. 算法——钻石金字塔(动态规划+贪心)

    钻石金字塔 一.实验题目 矿工从金字塔顶部一直走到金字塔底部,每次只能走左下或者右下方向,每个区域内有一定数量的钻石,求矿工所能开采到的钻石的最大数量 (1)矿工并不事先知道金字塔的钻石分布,但是他可 ...

  7. 【44. 通配符匹配】动态规划 / 贪心

    方法一: 动态规划 class Solution { public:bool isMatch(string s, string p) {int len_s=s.size();int len_p=p.s ...

  8. 动态规划/贪心总结(一)

    最长递增子序列(一维) 子序列是可以不连续的. ,dp[i]是i位置以num[i]结尾的最长子序列长度 状态转移方程: dp[i]=max(dp[i],dp[j]+1),j<i且满足num[i] ...

  9. 【LeetCode】LeetCode之跳跃游戏——动态规划+贪心算法

    [LeetCode]LeetCode之打家劫舍[暴力递归.动态规划.动态规划之优化空间的具体分析与实现] https://blog.csdn.net/Kevinnsm/article/details/ ...

最新文章

  1. NSLog不打印设置
  2. /*3.使用二维数组存储班上五个学生三门功课的考试成绩,要求输出每一个学生的总分、平均分、最高分、最低分。
  3. 数组和lookup函数
  4. pycharm+anaconda编译器运行程序时一直显示“ImportError: DLL load failed: 找不到指定的模块”的解决办法
  5. 计算机参观企业心得,走进联想 感悟联想——北航MBA参观联想集团总部
  6. Python基础 —— sys 模块
  7. mysql脚本之家_详细讲述MySQL中的子查询操作 (来自脚本之家)
  8. 苹果mac绘图软件:AutoCAD
  9. Mac OS X:解决开机总是显示“电脑关机是因为发生了问题”
  10. CopperCam入门手册[5]
  11. 计算机专业英语大作业,专业英语大作业
  12. 手把手带你玩转Spark机器学习-Spark的安装及使用
  13. NOIP 2017 列队 (线段树动态开点)
  14. 我的Blog——python封装为exe的注意事项(封装exe看这一篇基本就够了)
  15. 蓬莱小课:数据分析岗面试又问到MySQL索引?怎么回答看完你就明白了
  16. 第三届云计算大会 - 华为李三琦:云计算发展与华为运战略(转载)
  17. Python加密破解爬取七麦数据网APP榜单数据
  18. SAP采购申请审批策略配置
  19. 杂项-操作系统:操作系统百科
  20. 改程序...茅山后裔.....软件工程......linux kernel.....kde4....

热门文章

  1. SprimgMVC学习笔记(十)—— 拦截器
  2. 小米7的传闻:这是我们迄今为止知道的
  3. JAVA 邮件发送工具类
  4. UVA 12034 Race
  5. 设计模式笔记7:原型模式
  6. bzoj 4747: [Usaco2016 Dec]Counting Haybales
  7. Lesson 2 Installing the Oracle Database Software
  8. CentOS下crash分析内核kdump文件方法
  9. 8个应该了解的CSS3技术
  10. 雅虎开源CaffeOnSpark:基于Hadoop/Spark的分布式深度学习