zoukankan      html  css  js  c++  java
  • 树型动态规划 yongmou

      树型动态规划就是在“树”的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向:

      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;
    }

  • 相关阅读:
    2019-2020-1 20199302《Linux内核原理与分析》第九周作业
    MySQL 优化
    ElasticSearch实战
    redis实战
    ElasticSearch
    Zookeeper
    redis
    Jenkins 持续交付
    JDK 1.8 新特性之Stream
    cat-监控系统
  • 原文地址:https://www.cnblogs.com/liyongmou/p/1788509.html
Copyright © 2011-2022 走看看