• poj 2057 The Lost House 贪心思想在动态规划上的应用


      浅谈贪心思想在动态规划中的应用 ----- 黄劲松   论文中的例题,其中也附有详接

      讲讲自己的理解吧. 

      

      题目所求为, 使用某种特定策略,使从根节点rt ,依次到每个叶子节点最少步长. 再除以叶子节点数量. 即为最终期望值.

      对于一个以 rt 为根的子树上, 我们将其分为 House在子树rt上的步长总数Fa , 以及不在子树上步长总数Fb: 

           表示 House 在    该rt为根子树上的 步长总数

            表示 House 不在 该rt为根子树上的 步长总数

          表示 该子树上 叶子节点数量

      则所求期望为:

          

      

      若节点 u, 有 k 个子节点, 按照 s1, s2 , ... , sk 的固定顺序访问, 则  计算过程为:

        Fa(u) = 0; Fb(u) = 0;

        for( i = 1 ... k )

          Fa(u) += ( Fb(u)+1 ) * Leave( Si ) + Fa( Si )  // 若House在Si子树时, 前面 1..i-1 个已经走过,且数量是叠加,  此时走向 SI 子树时, +1 步长,其有 Leave( Si ) 个叶子节点,方案数要叠加 

          Fb(u) += Fb( Si ) + 2            // 若House不在 Si 子树,则返回 的步长花费

      

      使用数学公式表示为:

          

      现在的问题就是如何决定访问儿子的顺序,不同的访问顺序会产生不同的Fa[u]。我们要使得Fa[u]尽量的小。

      将公式进行处理可以得到如下:

          

      可以看到  若将 子节点  位置改变, 则对于公式 后两项没有影响,

      所以对于 子节点 间位置关系, 我们仅需考虑第一项就可以了

        令

           为 两子节点  顺序放置时 值。

          为 两子节点  交换放置时 值。

        则 两值做差 得到:

           

        所以我们得出结论, 顺序位置 则只跟元素  的信息有关,于别的元素的排列情况无关,所以元素  是可比的。

        所以我们可以根据此得出 任意 根节点u的子节点  (i,j) 两两间关系,

        又 对于 根节点 u 的任意三个子节点  a, b, c ,存在如下关系时: ( a < b, b < c ) 

            

            

        两式相乘后,得

            

        说明其满足 闭包传递性 , 则我们可以通过 先序关系 得出 全序关系, 即可得出 Fa( u )

    解题代码

      

    View Code
    // code by: yefeng1627
    // time: 2013-1-16
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    const int N = 1010;
    struct node
    {
        int fa,fb,L;
        bool flag;
    }T[N];
    
    vector<int> Q[N];
    int n;
    
    bool cmp( int x, int y )
    {return ( (T[x].fb+2)*T[y].L < (T[y].fb+2)*T[x].L );}
    void dfs( int u )
    {// return the fa(u)
        // 首先得到 u 的所有子节点信息    
        for(int i = 0; i < (int)Q[u].size(); i++)
            dfs( Q[u][i] );        
    
        // 初始化
        T[u].fa = T[u].fb = T[u].L = 0;
        
        // 叶子节点
        if( Q[u].size() == 0 ) T[u].L = 1;
    
        if( Q[u].size() > 0 ){
            sort( Q[u].begin(), Q[u].end(), cmp );    
            
            for(int i = 0; i < Q[u].size(); i++)
            {
                int v = Q[u][i];    
                T[u].fa += ( T[u].fb+1 )*T[v].L + T[v].fa;
                T[u].fb += T[v].fb+2;
                T[u].L += T[v].L;    
            }
            // 若节点u 上存在毛毛虫,则返回花费0    
            if( T[u].flag ) T[u].fb = 0;    
        }
    }
    int main()
    {
        while(    scanf("%d", &n) , n )
        {
            for(int i = 0; i <= n; i++)    Q[i].clear();
            char str[2];
            for(int x = 1; x <= n; x++)
            {
                int pre;    
                scanf("%d %s", &pre, str);
                if( pre != -1 ) Q[pre].push_back(x);    
                T[x].flag = ( (str[0]=='Y') ? true : false );
            }
            dfs(1);
            double ans = 1.0*T[1].fa/T[1].L;
            printf("%.4f\n", ans);
        //    printf("Fa(rt) = %d\n", T[1].fa );
        }
        return 0;
    }
  • 相关阅读:
    简单的生成编号的存储过程
    表实体上面添加特性获取到连接字符串
    Spring 静态注入讲解(MethodInvokingFactoryBean)
    嵌套的SQL另外一种写法
    微信小程序之列表下拉加载更多
    微信小程序之--->轮播图制作
    javascript变量作用域
    struts2升级报ActionContextCleanUp<<is deprecated。Please use the new filters
    java日期加减
    数字转大写
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2863442.html
Copyright © 2020-2023  润新知