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 节点为jdp[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; }
相关文章推荐
- bzoj3529: [Sdoi2014]数表
- python中去除列表重复元素的方法汇总
- MFC 最小化到托盘及右击托盘菜单
- SmartImageView
- Add a Syscall
- select/poll/epoll on serial port
- Android Studio导入项目非常慢的解决办法
- JavaScript之函数和this
- 排序—基数排序(js实现)
- 并查集+欧拉回路
- Generate Ubuntu Install Media On Mac
- 遥望布达拉——DAY14 左贡-邦达
- Cordys BOP租户使用中常见疑问——租户对接口进行授权
- 动态规划-三角形
- C语言结构体
- Tomcat设置IP,实现局域网内机器访问
- 【转】细说new与malloc的10点区别
- Bare Medal on BCM2835 and BCM2836
- 第十篇 javascript基础语法
- java简单数据类型