树型动态规划
2010-07-30 10:38
99 查看
树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向:
1. 根—>叶:不过这种动态规划在实际的问题中运用的不多,也没有比较明显的例题,所以不在今天讨论的范围之内。
2. 叶->根:既根的子节点传递有用的信息给根,完后根得出最优解的过程。这类的习题比较的多,下面就介绍一些这类题目和它们的一般解法。
树本身就是一个递归的结构,所以在树上进行动态规划或者递推是在合适不过的事情。
必要条件:子树之间不可以相互干扰,如果本来是相互干扰的,那么我们必须添加变量使得他们不相互干扰。
题目:
1. POJ 1463 Strategic game
一城堡的所有的道路形成一个n个节点的树,如果在一个节点上放上一个士兵,那么和这个节点相连的边就会被看守住,问把所有边看守住最少需要放多少士兵。
dproot[ i ]表示以i为根的子树,在i上放置一个士兵,看守住整个子树需要多少士兵。
all[ i ]表示看守住整个以i为根的子树需要多少士兵。
状态转移方程:
叶子节点:dproot[k] =1; all[k] = 0;
非叶子节点: dproot[i] = 1 + ∑all[j](j是i的儿子);
all[i] = min( dproot[i], ∑dproot[j](j是i的儿子) ),决策是否在i点放士兵
代码:
代码
1. 根—>叶:不过这种动态规划在实际的问题中运用的不多,也没有比较明显的例题,所以不在今天讨论的范围之内。
2. 叶->根:既根的子节点传递有用的信息给根,完后根得出最优解的过程。这类的习题比较的多,下面就介绍一些这类题目和它们的一般解法。
树本身就是一个递归的结构,所以在树上进行动态规划或者递推是在合适不过的事情。
必要条件:子树之间不可以相互干扰,如果本来是相互干扰的,那么我们必须添加变量使得他们不相互干扰。
题目:
1. POJ 1463 Strategic game
一城堡的所有的道路形成一个n个节点的树,如果在一个节点上放上一个士兵,那么和这个节点相连的边就会被看守住,问把所有边看守住最少需要放多少士兵。
dproot[ i ]表示以i为根的子树,在i上放置一个士兵,看守住整个子树需要多少士兵。
all[ i ]表示看守住整个以i为根的子树需要多少士兵。
状态转移方程:
叶子节点:dproot[k] =1; all[k] = 0;
非叶子节点: dproot[i] = 1 + ∑all[j](j是i的儿子);
all[i] = min( dproot[i], ∑dproot[j](j是i的儿子) ),决策是否在i点放士兵
代码:
代码
//在poj上这个题用list超时了,用vector就360ms #include <cstdio> #include <vector> using namespace std; #define MAX 1500 int n; int root; vector<int> tree[MAX]; int dproot[MAX]; //dproot[i]表示以i为根的子树,在i上放置一个士兵,看守住整个子树需要多少士兵 int all[MAX]; //all[i]表示看守住以i为根的子树需要多少士兵 void DFS(int r){ vector<int>::iterator it; if(!tree[r].empty()){ int sum_root, sum_all; sum_root = sum_all = 0; for(it=tree[r].begin(); it != tree[r].end(); ++it){ DFS(*it); sum_root += dproot[*it]; sum_all += all[*it]; } //状态转移方程 dproot[r] = 1 + sum_all;//r放了一个士兵,其儿子可放可不放 all[r] = min(dproot[r], sum_root); //决策:r放士兵、不放士兵 } else{ dproot[r] = 1; all[r] = 0; } } bool read_data(){ if(scanf("%d", &n) == EOF) return false; int i, j; for(i=0; i<n; ++i) if(!tree[i].empty()) tree[i].clear(); int m, u, v; scanf("%d:(%d)", &u, &m); root = u; for(i=0; i<m; ++i){ scanf("%d", &v); tree[u].push_back(v); } for(i=1; i<n; ++i){ scanf("%d:(%d)", &u, &m); for(j=0; j<m; ++j){ scanf("%d", &v); tree[u].push_back(v); } } return true; } int main() { // freopen("in", "r", stdin); while(read_data()){ DFS(root); printf("%d\n", all[root]); } return 0; }
相关文章推荐
- 树型动态规划练习总结
- POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心)-动态规划做法
- 树型动态规划(树形dp)
- POJ2342 树型动态规划
- POJ1463 树型动态规划
- POJ 3398 Perfect Service(树型动态规划,最小支配集)
- ALGO-4 结点选择 — 树型动态规划(java再优化版)
- POJ 2342 Anniversary party / HDU 1520 Anniversary party / URAL 1039 Anniversary party(树型动态规划)
- 树型动态规划
- 访问艺术馆(树型动态规划)
- POJ 3342 Party at Hali-Bula / HDU 2412 Party at Hali-Bula / UVAlive 3794 Party at Hali-Bula / UVA 1220 Party at Hali-Bula(树型动态规划)
- 皇宫看守 树型动态规划
- POJ 2152 fire / SCU 2977 fire(树型动态规划)
- 树型动态规划练习题:【bzoj1017】[JSOI2008]魔兽地图DotR
- 动态规划----树型动态规划
- CJOJ 1976 二叉苹果树 / URAL 1018 Binary Apple Tree(树型动态规划)
- ALGO-4 结点选择 — 树型动态规划(java)
- 树型动态规划练习题:【bzoj2815】[ZJOI2012]灾难
- CJOJ 2171 火车站开饭店(树型动态规划)
- CJOJ 1010【NOIP2003】加分二叉树 / Luogu 1040 加分二叉树(树型动态规划)