ZOJ 2366 Weird Dissimilarity (简单DP)
2015-07-13 13:09
525 查看
题意:
字符c1和c2的距离为d(c1, c2),已知两个字符串s和t,现在要找长度相等的两个字符串a和b,使得s是a的子序列,t是b的子序列,且a和b的距离最小。
思路:
字串和子序列是不一样的。。。。子序列是允许中间 间断 的,而字串必须是连续的...比赛的时候居然理解错了....T_T
这样的话,用最长公共子序列的思路来解决这道题就好啦~
dp[i][j]表示 “第一个串处理到第i个字符,第二个串处理到第j个字符” 时,最短的距离是什么。。
然后这种两个串的题目见的很多啦....很好转移啊!详见代码
后面用一些值 需要预处理一下然后保存下来~、、
路径输出使题目变得麻烦了一些啊..再根据刚才DP求得的最优值dfs回去 然后记录结果就好啦~
code:
ps 可以学到路径打印的思路~~
然后这种两行的题目真的是见了许多了....然而并不怎么会....昨晚题目一定要注意多想想啦。。。
比赛的时候队友读错题真的是没办法....自己拿到题目要先确认一下呀..T_T。。。sigh...
字符c1和c2的距离为d(c1, c2),已知两个字符串s和t,现在要找长度相等的两个字符串a和b,使得s是a的子序列,t是b的子序列,且a和b的距离最小。
思路:
字串和子序列是不一样的。。。。子序列是允许中间 间断 的,而字串必须是连续的...比赛的时候居然理解错了....T_T
这样的话,用最长公共子序列的思路来解决这道题就好啦~
dp[i][j]表示 “第一个串处理到第i个字符,第二个串处理到第j个字符” 时,最短的距离是什么。。
然后这种两个串的题目见的很多啦....很好转移啊!详见代码
后面用一些值 需要预处理一下然后保存下来~、、
路径输出使题目变得麻烦了一些啊..再根据刚才DP求得的最优值dfs回去 然后记录结果就好啦~
code:
#include<cstdio> #include<cstring> #include<cstdlib> #include<string> #include<vector> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f //----------------------------------- const int maxn = 2005; int z[maxn], lz; int s[maxn], ls, t[maxn], lt; int dist[maxn][maxn], va[maxn], vb[maxn]; int f[maxn][maxn]; int ansa[maxn*2], ansb[maxn*2], ca[maxn], cb[maxn], cnt; void change(char *ss, int *tmp){ int len = strlen(ss); for(int i = 0; i < len; i++){ tmp[i+1] = ss[i]; } } void init(){ char tmp[maxn]; scanf("%s", tmp); lz = strlen(tmp); change(tmp, z); scanf("%s", tmp); ls = strlen(tmp); change(tmp, s); scanf("%s", tmp); lt = strlen(tmp); change(tmp, t); int u, v; for(int i = 1; i <= lz; i ++){ u = z[i]; for(int j = 1; j <= lz; j++){ v = z[j]; scanf("%d",&dist[u][v]); } } memset(va, INF, sizeof(va)); memset(vb, INF, sizeof(vb)); for(int i = 1; i <= lz; i++){ for(int j = 1; j <= lz; j++){ u = z[i], v = z[j]; if(va[u] > dist[u][v]){ va[u] = dist[u][v]; ca[u] = v; } if(vb[u] > dist[v][u]){ vb[u] = dist[v][u]; cb[u] = v; } // va[u] = min(va[u], dist[u][v]); // vb[u] = min(vb[u], dist[v][u]); } } } int DP(int i, int j){ if(f[i][j] != INF) return f[i][j]; if(i == 0 && j == 0) return f[i][j] = 0; if(i > 0) f[i][j] = min(f[i][j], DP(i-1, j) + va[s[i]]); if(j > 0) f[i][j] = min(f[i][j], DP(i, j-1) + vb[t[j]]); if(i > 0 && j > 0) f[i][j] = min(f[i][j], DP(i-1, j-1) + dist[s[i]][t[j]]); return f[i][j]; } void dfs(int i, int j){ int ans = f[i][j]; if(i > 0 && j > 0 && ans == f[i-1][j-1] + dist[s[i]][t[j]]){ ansa[cnt] = s[i]; ansb[cnt] = t[j]; cnt++; dfs(i-1, j-1); return; } if(i > 0 && ans == f[i-1][j] + va[s[i]]){ ansa[cnt] = s[i]; ansb[cnt] = ca[s[i]]; cnt++; dfs(i-1, j); return; } if(j > 0 && ans == f[i][j-1] + vb[t[j]]){ ansa[cnt] = cb[t[j]]; ansb[cnt] = t[j]; cnt++; dfs(i, j-1); return ; } } void solve(){ memset(f, INF, sizeof(f)); int ans = DP(ls, lt); printf("%d\n",ans); cnt = 0; dfs(ls, lt); for(int i = cnt-1; i >= 0; i--){ printf("%c",ansa[i]); } printf("\n"); for(int i = cnt-1; i >= 0; i--){ printf("%c",ansb[i]); } printf("\n"); } int main(){ init(); solve(); return 0; }
ps 可以学到路径打印的思路~~
然后这种两行的题目真的是见了许多了....然而并不怎么会....昨晚题目一定要注意多想想啦。。。
比赛的时候队友读错题真的是没办法....自己拿到题目要先确认一下呀..T_T。。。sigh...
相关文章推荐
- leetCode 47.Permutations II (排列组合II) 解题思路和方法
- 程序猿的世界
- Ajax实现异步操作实例_针对XML格式的请求数据
- [ActionScript 3.0] 动态绘制扇形实例(拖拽绘制)
- 类中重载和重写的区别
- 字符串常量演示Demo
- Codeforces Round #260 (Div. 2) D. A Lot of Games
- 【英语】20150713 生词
- 字符串常量演示Demo
- OAF_开发系列17_实现OAF数组应用Vector / Hashmap / Hashtable / Arraylist(案例)
- angularJS socket
- [ActionScript 3.0] 绘制扇形方法
- HTTP/2笔记之错误处理和安全
- GRE写作必备句型
- NSData 与NSString Byte UIImage之间的转换
- 《iOS总结》APP上传步骤(详细版)
- 一句代码搞定,所有页面点击空白处隐藏键盘
- hibernate实体类型映射文件
- 第一份工作
- HTTP/2笔记之消息交换