【TOJ 1139】Compromise【DP】

11 篇文章 0 订阅

裸的最长公共子序列,不过这里需要保存路径。

#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;

map<string,int>stod;
map<int,string>dtos;
char w[40];
int dp[110][110], n1[110], n2[110], pre[110][110];
vector<int>ans;

int main() {
    int i, j, id, l1, l2;
    while (~scanf("%s", w)) {
        id = 0, stod.clear(), dtos.clear();
        stod[w] = id, dtos[id] = w;
        l1 = l2 = 1;
        n1[l1++] = id++;
        while (scanf("%s", w)) {
            if (strcmp(w, "#") == 0) break;
            if (stod.find(w) == stod.end()) stod[w] = id, dtos[id++] = w;
            n1[l1++] = stod[w];
        }
        while (scanf("%s", w)) {
            if (strcmp(w, "#") == 0) break;
            if (stod.find(w) == stod.end()) stod[w] = id, dtos[id++] = w;
            n2[l2++] = stod[w];
        }
        memset(dp, 0, sizeof(dp));
        memset(pre, -1, sizeof(pre));
        int t1, t2;
        for (i = 1;i < l1;i++) {
            for (j = 1;j < l2;j++) {
                if (n1[i] == n2[j]) {
                    t1 = dp[i-1][j-1]+1;
                    if (t1 > dp[i][j]) dp[i][j] = t1, pre[i][j] = (i-1)*1000+j-1;
                }else {
                    t1 = dp[i-1][j], t2 = dp[i][j-1];
                    if (t1 > dp[i][j]) dp[i][j] = t1, pre[i][j] = (i-1)*1000+j;
                    if (t2 > dp[i][j]) dp[i][j] = t2, pre[i][j] = i*1000+j-1;
                }
            }
        }
        ans.clear();
        t1 = l1-1, t2 = l2-1;
        while (pre[t1][t2] != -1) {
            if (n1[t1] == n2[t2]) ans.push_back(n1[t1]);
            int tm = pre[t1][t2];
            t1 = tm/1000, t2 = tm%1000;
        }
        if (ans.size() == 0) {puts("");continue;}
        for (i = ans.size()-1;i > 0;i--) cout << dtos[ans[i]] << " ";
        cout << dtos[ans[i]] << endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值