zoukankan      html  css  js  c++  java
  • 2016集训测试赛(十八)Problem C: 集串雷 既分数规划学习笔记

    Description

    Solution

    分数规划经典题. 话说我怎么老是忘记分数规划怎么做呀...
    所以这里就大概写一下分数规划咯:
    分数规划解决的是这样一类问题: 有(a_1, a_2 ... a_n)(b_1, b_2 ... b_n)这样一些值(其中(b)严格大于零), 其中(a)(b)之间存在某种联系; 要你决策出每个(a_k), 使得

    [ans = frac{sum_{x = 1}^n a_x}{sum_{x = 1}^n b_x} ]

    取得最大值或最小值.
    考虑怎样解决: 考虑二分(ans), 找到一个最大的(ans)使得

    [frac{sum_{x = 1}^n a_x}{sum_{x = 1}^n b_x} ge ans ]

    稍作变换, 得到

    [sum_{x = 1}^n a_x ge ans sum_{x = 1}^n b_x \ sum_{x = 1}^n a_x - b_x imes ans ge 0 ]

    在每个位置(i)上决策(a)(b)即可.
    换到这一题, 直接照搬上述思路即可, 不再赘述了.

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    namespace Zeonfai
    {
        inline int getInt()
        {
            int a = 0, sgn = 1; char c;
            while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
            while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
            return a * sgn;
        }
    }
    const int N = 500;
    int suc[N + 1][2], a[N + 1], b[N + 1], sz[N + 1];
    double f[N << 2][N + 2];
    int main()
    {
    
        #ifndef ONLINE_JUDGE
    
        freopen("zs.in", "r", stdin);
        freopen("zs.out", "w", stdout);
    
        #endif
    
        using namespace Zeonfai;
        int n = getInt(), cnt = n;
        for(int i = 1; i <= n; ++ i)
        {
            for(int j = 0; j < 2; ++ j)
            {
                _suc[i][j] = getInt();
                if(! _suc[i][j]) suc[i][j] = ++ cnt;
            }
            a[i] = getInt(); b[i] = getInt();
        }
        for(int i = cnt; i > n; -- i) sz[i] = 1;
        for(int i = n; i; -- i) sz[i] = sz[suc[i][0]] + sz[suc[i][1]];
        double L = 0, R = 10, ans;
        while(R - L > 1e-5)
        {
            double mid = (R + L) / 2;
            for(int i = 1; i <= n; ++ i) for(int j = 0; j <= n + 1; ++ j) f[i][j] = - 1e9;
            for(int i = cnt; i > n; -- i) for(int j = 0; j < 2; ++ j) f[i][j] = 0;
            for(int i = n; i; -- i) for(int j = 0; j <= sz[suc[i][0]]; ++ j) for(int k = 0; k <= sz[suc[i][1]]; ++ k)
                f[i][j + k] = max(f[i][j + k], f[suc[i][0]][j] + f[suc[i][1]][k] + abs(j - k) * a[i] - mid * (j ^ k ^ b[i]));
            int flg = 0;
            for(int i = 0; i <= sz[1]; ++ i) if(f[1][i] >= mid) flg = 1;
            if(flg) ans = mid, L = mid; else R = mid;
        }
        printf("%.2lf
    ", ans);
    }
    
    
  • 相关阅读:
    设计模式之适配器模式(Adapter)
    数组中的趣味题(二)
    VSTS 2008 自定义签入代码审查策略
    自定义 Vista 系统下程序运行级别
    全国省份,城市,地区全数据(SQL版与XML版)包括各城市邮编
    LINQ 从数据库读数据生成 XML
    IE 8 Beta 2 初体验 隐藏了的"IE7模式"
    利用宏帮助快速录入代码
    你现在的生活是你n年前决定的
    控制参数个数的几种方式
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7464983.html
Copyright © 2011-2022 走看看