poj1934 Trip【线性DP】【输出方案】
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 3850 | Accepted: 1030 |
Description
As they want to travel together, they have to agree on a common route. None wants to change the order of the cities on his or her route or add other cities. Therefore they have no choice but to remove some cities from the route. Of course the common route should be as long as possible.
There are exactly 26 cities in the region. Therefore they are encoded on the lists as lower case letters from 'a' to 'z'.
Input
Each list consists of 1 to 80 lower case letters with no spaces inbetween.
Output
Sample Input
abcabcaa
acbacba
Sample Output
ababa
abaca
abcba
acaba
acaca
acbaa
acbca
Source
题意:
求最长公共子序列,要求输出所有方案。
思路:
最长公共子序列好求,难点在输出方案。
用dp[i][j]表示处理到alice[i]和bob[j]时的最优解。如果alice[i]bob[j]不相等,dp[i][j]从dp[i-1][j], dp[j][i-1]中取较大的。相等,则dp[i-1][j-1]+1
先得到最优解,然后我们来输出所有方案。排序和去重都简单,用个set就行了。
首先我们预处理出alice串1~i的子串中,字符j+'a'最后一次出现的位置,存入pos1[i][j]。对bob串也做同样的处理。
然后我们进行递归。len1表示alice子串长度,len2表示bob子串长度,len表示公共串的子串长度。
枚举26个字母,找到他们在子串中最后出现的位置,如果我们发现dp[p1][p2] = len,那么说明这是一种可行的方案。并且这表示,这个字母会出现在这个方案的len位置。于是我们继续递归,去找(len1-1,len2-1,len-1)。直到len小于0了,说明现在当前跑出来的这个串跑完了,他是一个完整的方案,insert进set。如果在len到0之前,len1或者len2就已经小于0了,说明这个方案最后不可行了,也就不会insert,而会回溯。整个过程相当于是一个dfs。
WA了一次是因为输出了一下方案数的个数.....
//#include <bits/stdc++.h>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<stdio.h>
#include<cstring>
#include<vector>
#include<map>
#include<set> #define inf 0x3f3f3f3f
using namespace std;
typedef long long LL; char alice[], bob[], tmp[];
int dp[][], pos1[][], pos2[][];
set<string> ans;
int lena, lenb; void solve(int len1, int len2, int len)
{
if(len <= ){
string str;
str = tmp + ;
//memset(tmp, 0, sizeof(tmp));
//cout<<str<<endl;
ans.insert(str);
return;
}
if(len1 > && len2 > ){
for(int i = ; i < ; i++){
int p1 = pos1[len1][i];
int p2 = pos2[len2][i];
if(dp[p1][p2] == len){
tmp[len] = i + 'a';
solve(p1 - , p2 - , len - );
}
}
} } int main()
{
while(scanf("%s%s", alice + , bob + ) != EOF){
lena = strlen(alice + );
lenb = strlen(bob + );
//ans.clear(); for(int i = ; i <= lena; i++){
dp[i][] = ;
}
for(int j = ; j <= lenb; j++){
dp[][j] = ;
} int tmpi = -, tmpj = -;
for(int i = ; i <= lena; i++){
for(int j = ; j <= lenb; j++){
dp[i][j] = max(dp[i][j], dp[i - ][j]);
dp[i][j] = max(dp[i][j], dp[i][j - ]);
if(alice[i] == bob[j]){
dp[i][j] = dp[i - ][j - ] + ;
}
}
} memset(pos1, -, sizeof(pos1));
memset(pos2, -, sizeof(pos2));
for(int i = ; i <= lena; i++){
for(int j = ; j < ; j++){
if(alice[i] == j +'a'){
pos1[i][j] = i;
}
else{
pos1[i][j] = pos1[i - ][j];
}
}
}
for(int i = ; i <= lenb; i++){
for(int j = ; j < ; j++){
if(bob[i] == j + 'a'){
pos2[i][j] = i;
}
else{
pos2[i][j] = pos2[i - ][j];
}
}
} //printf("%d\n", dp[lena][lenb]);
memset(tmp, , sizeof(tmp));
solve(lena, lenb, dp[lena][lenb]);
set<string>::iterator iter;
for(iter = ans.begin(); iter != ans.end(); iter++){
cout<<*iter<<endl;
} } return ;
}
poj1934 Trip【线性DP】【输出方案】的更多相关文章
- $Poj1934\ Trip$ 线性$DP+$搜索
Luogu Description 爱丽丝和鲍伯想去度假,他们每个人都制定了一个参观城市的清单,该地区正好有26个城市,因此它们被编码为小写字母“a”到“z”.清单上可能重复出现某个城市.因为他们想一 ...
- 【题解】POJ1934 Trip (DP+记录方案)
[题解]POJ1934 Trip (DP+记录方案) 题意: 传送门 刚开始我是这么设状态的(谁叫我DP没学好) \(dp(i,j)\)表示钦定选择\(i\)和\(j\)的LCS,然而你会发现这样钦定 ...
- 线性dp
线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...
- 线性DP之机器分配
题目大意 自己瞅 (懒得打了) 思路 前面是很简单的线性dp,后面是模拟递归输出方案, 模拟递归可以设ny为机器数机器数,nx表示第nx个公司,tot为总盈利,那么则有\(a[nx][i]+dp[nx ...
- LightOJ1044 Palindrome Partitioning(区间DP+线性DP)
问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...
- Codeforces 176B (线性DP+字符串)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...
- hdu1712 线性dp
//Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...
- 动态规划——线性dp
我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...
- POJ 2479-Maximum sum(线性dp)
Maximum sum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33918 Accepted: 10504 Des ...
- poj 1050 To the Max(线性dp)
题目链接:http://poj.org/problem?id=1050 思路分析: 该题目为经典的最大子矩阵和问题,属于线性dp问题:最大子矩阵为最大连续子段和的推广情况,最大连续子段和为一维问题,而 ...
随机推荐
- 使用ffmpeg实现合并多个音频为一个音频的方法
使用ffmpeg实现合并多个音频为一个音频的方法可以使用ffmpeg的filter功能来进行这个操作,而且效果很好amerge也可以实 使用ffmpeg实现合并多个音频为一个音频的方法 可以使用ffm ...
- nodejs基础 -- buffer缓冲区
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型.但在处理像TCP流或文件流时,必须使用到二进制数据.因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存 ...
- Sublime Text3打造U盘便携Lua IDE
下载Sublime Text 链接http://www.sublimetext.com/3 我下载的是win32 portable 版 便于放入U盘携带 解压 注冊: 能够复制下面部分直接贴入注冊栏 ...
- WiFi(网络)调试Android手机
手机需要root 使用adb tcpip命令开启网络调试功能,一旦手机重启,又要重复这些步骤,比较麻烦. 一劳永逸的方法是,使用re管理器(给予root权限)在手机的/system/build.pro ...
- jQuery-修改元素属性
1.attr方法 获取匹配的元素集合中的第一个元素的属性的值 或 设置匹配元素指定的属性 使用说明: 1)只传一个参数的情况: 1>字符串(属性名称) 只传一个字符串属性名称 表示获取匹配的元素 ...
- kafka学习之-深入研究原理
参考博客: http://www.cnblogs.com/fxjwind --阿里牛人 http://blog.csdn.net/lizhitao/article/details/41778193 ...
- Ubuntu 安装 Oracle11gR2:'install' of makefile '/home/oracle/app/oracle/product/11.2.0/dbhome_1/ctx/lib/ins_ctx.mk'
网上包括官方,就是教给你如何安装依赖包什么的:libstdc++5,但很麻烦:既要下载找相关的包,还不一定能安装的上. 其实,仅仅是为了安装,直接从二进制的deb包里,解压一个 “libstdc++. ...
- VR资源浏览网站
https://my.matterport.com 资源 https://my.matterport.com/show/?m=kCeVCzCjQ5s
- Python 高斯坐标转经纬度算法
# 高斯坐标转经纬度算法# B=大地坐标X# C=大地坐标Y# IsSix=6度带或3度带def GetLatLon2(B, C,IsSix): #带号 D = math.trunc(C / 1000 ...
- Linux之MySQL
一:卸载旧版本 使用下面的命令检查是否安装有MySQL Server rpm -qa | grep mysql 有的话通过下面的命令来卸载掉 rpm -e mysql //普通删除模式 rpm -e ...