2015Daejeon UVALive 7236 K - Tree Edit

来源:互联网 发布:小约翰 震惊 知乎 编辑:程序博客网 时间:2024/05/22 14:53

题目描述:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=104527#problem/K

题解:

原始树 叫 1 上面的节点为i 目标树叫2 节点为j

dp[i][j] 就是i节点和j节点到时候对应所花的目前的次数

然后树形dp

现在看dfs(i, j)怎么算 算出来的结果放到dp[i][j]中
设i的儿子a个 j b 个儿子,
那么我们用dp来算这一层,应该有f[a][b]个状态. 代表1树处理到a ,2树处理到b时的花费的次数. f的转移是o(1)的

看起来是一个n^4的dp
但是其实不是. 看每个节点被算了几次
只有往他父亲推的那一次才会被算一次, 算的复杂度上限是另外一棵树的节点个数
也可以说是每个i j 二元组只会被算一次,所以是n^2的

重点:

1.dp定状态暴力的思路很显然.
2.每一层相当于两个序列去对应的想法,用dp
3.复杂度的分析

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <vector>using namespace std;const int maxn  = 1000 + 100;const int INF = 1e8;int n, m, f[maxn][maxn], dp[maxn][maxn], num[2][maxn];char lab[2][maxn];vector<int> G[2][maxn];char s[maxn * maxn];int cnt;void dfs_pre(vector<int> G[], int u, int num[]) {    num[u] = 1;    for(int i = 0; i < G[u].size(); i++) {        int v = G[u][i];        dfs_pre(G, v, num);        num[u] += num[v];    }}void dfs(int u, int v) {    int ans = 0;    if(lab[0][u] != lab[1][v])        ans++;    for(int i = 0; i < G[0][u].size(); i++) {        for(int j = 0; j < G[1][v].size(); j++) {            dfs(G[0][u][i], G[1][v][j]);        }    }    int tmp = INF;    f[0][0] = 0;    for(int i = 0; i <= G[0][u].size(); i++) {        for(int j = 0; j <= G[1][v].size(); j++) {            if(i ==0 && j == 0)                continue;            int id[2];            if(i != 0)                id[0] = G[0][u][i - 1];            if(j != 0)                id[1] = G[1][v][j - 1];            if(i == 0) {                f[i][j] = f[i][j - 1] + num[1][id[1]];            }            else if(j == 0) {                f[i][j] = f[i - 1][j] + num[0][id[0]];                continue;            }            else {                f[i][j] = f[i - 1][j - 1] + dp[id[0]][id[1]];                f[i][j] = min(f[i][j], f[i-1][j] + num[0][id[0]]);                f[i][j] = min(f[i][j], f[i][j - 1] + num[1][id[1]]);            }        }    }    ans += f[G[0][u].size()][G[1][v].size()];    dp[u][v] = ans;}void solve() {    dfs_pre(G[0], 1, num[0]);    dfs_pre(G[1], 1, num[1]);    dfs(1, 1);    printf("%d\n", dp[1][1]);}int initail(int pos, vector<int> G[], char lab[]) {    cnt++;    lab[cnt] = s[pos];    int u = cnt;    int i = pos + 1;    while(s[i] != ')') {        G[u].push_back(cnt+1);        i = initail(i + 1, G, lab);    }    return i + 1;}void dfs_out(int u, vector<int> G[], char lab[]) {    printf("%c    :\n", lab[u]);    for(int i = 0; i < G[u].size(); i++) {        int v = G[u][i];        printf("%c ", lab[v]);    }    printf("\n");    for(int i = 0; i < G[u].size(); i++) {        int v = G[u][i];        dfs_out(v, G, lab);    }}int main() {    //freopen("k.txt", "r", stdin);    int ncase;    scanf("%d", &ncase);    while(ncase--) {        for(int i = 1; i <= 1000; i++) {            G[0][i].clear();            G[1][i].clear();        }        scanf("%s", s);        cnt = 0;        initail(1, G[0], lab[0]);        //printf("11 %d\n", G[0][1].size());        //dfs_out(1, G[0], lab[0]);        scanf("%s", s);        cnt = 0;        initail(1, G[1], lab[1]);        solve();    }    return 0;}
0 0
原创粉丝点击