您的位置:首页 > 其它

2015Daejeon UVALive 7236 K - Tree Edit

2016-01-21 22:30 351 查看

题目描述:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: