zoukankan      html  css  js  c++  java
  • poj1934 Trip【线性DP】【输出方案】

    Trip
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 3850   Accepted: 1030

    Description

    Alice and Bob want to go on holiday. Each of them has planned a route, which is a list of cities to be visited in a given order. A route may contain a city more than once. 
    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

    The input consists of two lines; the first line is Alice's list, the second line is Bob's list. 
    Each list consists of 1 to 80 lower case letters with no spaces inbetween.

    Output

    The output should contain all routes that meet the conditions described above, but no route should be listed more than once. Each route should be printed on a separate line. There is at least one such non-empty route, but never more than 1000 different ones. Output them in ascending order.

    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了一次是因为输出了一下方案数的个数.....

      1 //#include <bits/stdc++.h>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<stdio.h>
      6 #include<cstring>
      7 #include<vector>
      8 #include<map>
      9 #include<set>
     10 
     11 #define inf 0x3f3f3f3f
     12 using namespace std;
     13 typedef long long LL;
     14 
     15 
     16 char alice[100], bob[100], tmp[100];
     17 int dp[100][100], pos1[100][100], pos2[100][100];
     18 set<string> ans;
     19 int lena, lenb;
     20 
     21 void solve(int len1, int len2, int len)
     22 {
     23     if(len <= 0){
     24         string str;
     25         str = tmp + 1;
     26         //memset(tmp, 0, sizeof(tmp));
     27         //cout<<str<<endl;
     28         ans.insert(str);
     29         return;
     30     }
     31     if(len1 > 0 && len2 > 0){
     32         for(int i = 0; i < 26; i++){
     33             int p1 = pos1[len1][i];
     34             int p2 = pos2[len2][i];
     35             if(dp[p1][p2] == len){
     36                 tmp[len] = i + 'a';
     37                 solve(p1 - 1, p2 - 1, len - 1);
     38             }
     39         }
     40     }
     41 
     42 }
     43 
     44 int main()
     45 {
     46     while(scanf("%s%s", alice + 1, bob + 1) != EOF){
     47         lena = strlen(alice + 1);
     48         lenb = strlen(bob + 1);
     49         //ans.clear();
     50 
     51         for(int i = 0; i <= lena; i++){
     52             dp[i][0] = 0;
     53         }
     54         for(int j = 0; j <= lenb; j++){
     55             dp[0][j] = 0;
     56         }
     57 
     58         int tmpi = -1, tmpj = -1;
     59         for(int i = 1; i <= lena; i++){
     60             for(int j = 1; j <= lenb; j++){
     61                 dp[i][j] = max(dp[i][j], dp[i - 1][j]);
     62                 dp[i][j] = max(dp[i][j], dp[i][j - 1]);
     63                 if(alice[i] == bob[j]){
     64                     dp[i][j] = dp[i - 1][j - 1] + 1;
     65                 }
     66             }
     67         }
     68 
     69         memset(pos1, -1, sizeof(pos1));
     70         memset(pos2, -1, sizeof(pos2));
     71         for(int i = 1; i <= lena; i++){
     72             for(int j = 0; j < 26; j++){
     73                 if(alice[i] == j +'a'){
     74                     pos1[i][j] = i;
     75                 }
     76                 else{
     77                     pos1[i][j] = pos1[i - 1][j];
     78                 }
     79             }
     80         }
     81         for(int i = 1; i <= lenb; i++){
     82             for(int j = 0; j < 26; j++){
     83                 if(bob[i] == j + 'a'){
     84                     pos2[i][j] = i;
     85                 }
     86                 else{
     87                     pos2[i][j] = pos2[i - 1][j];
     88                 }
     89             }
     90         }
     91 
     92         //printf("%d
    ", dp[lena][lenb]);
     93         memset(tmp, 0, sizeof(tmp));
     94         solve(lena, lenb, dp[lena][lenb]);
     95         set<string>::iterator iter;
     96         for(iter = ans.begin(); iter != ans.end(); iter++){
     97             cout<<*iter<<endl;
     98         }
     99 
    100     }
    101 
    102     return 0;
    103 }
  • 相关阅读:
    向日葵、阳光
    laravel还是给我太多惊喜了
    滴滴笔试题——小试牛刀
    剑指offer——二叉搜索树的后序遍历序列
    2019春招美团笔试
    首次实习生招聘会——航天一院
    有趣的数字
    剑指offer——从上往下打印二叉树
    剑指offer——栈的压入、弹出序列
    剑指offer——包含min函数的栈
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9774766.html
Copyright © 2011-2022 走看看