Luo Gu P4377 [USACO18OPEN] Talent Show + scores planning

Fractional Programming

Scores planning can be used to deal with issues related to the ratio of the fraction that is.

And scores generally not set up a separate planning problem, but to and DP, graph theory, network flow algorithms together.

The basic approach is generally through the half.

Half title we all know, what minimum or maximum request, half what it is.

Minimum or maximum value which are monotone.

The current maximum value is set \ (MAXN \) , if there is a ratio such that the ratio \ (MAXN \) large, the \ (Y / X> MAXN \) , to give simplification: \ (YX * MAXN> 0 \)

You can update the answer. Dichotomy is satisfied (i.e. \ (MAXN \) the larger the \ (X * Y-MAXN \) ) smaller, the more difficult to update answers.

And two check points can be determined by sorting \ (y [i] -x [ i] * maxn \) of the maximum value, and then directly take the maximum greedy, and finally determines whether to is greater than 0

This topic

For this problem, the greedy ordering requirements, then it is not considered a maximum value, because there is a weight limit, it is possible to use a backpack.

Weight is the weight of the original data, that is, the value \ (Y [I] the -X-[I] * MAXN \) , during the transfer all the required weight is greater than W are transferred to the final W

Finally, statistical convenience.

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m, dp[100100];
struct dat {        
    int w, t;       
    int bizhi;      
}data[1001000];     
bool check(int mid) 
{                   
    memset(dp, 128, sizeof(dp));
    dp[0] = 0;      
    for (int i = 1; i <= n; i++)
        data[i].bizhi = data[i].t - mid * data[i].w;
    int ha = dp[m]; 
    for (int i = 1; i <= n; i++)
        for (int j = m; j >= 0; j--)
            if (dp[j] != ha)
                dp[min(m, j + data[i].w)] = max(dp[min(m, j + data[i].w)], dp[j] + data[i].bizhi);//取min的意义是为了让所有质量都大于m的都转移到一个地方 
    if (dp[m] >= 0) return 1;//如果存在一个价值使得能够>=0即满足条件,则该mid可以,寻找更大的 
    else return 0;  
}                   
signed main()                                               
{                   
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%lld%lld", &data[i].w, &data[i].t), data[i].t *= 1000;
    int l = 0, r = 150000, ans;
    while (l <= r)  
    {
        int mid = (l + r) / 2;
        if (check(mid))     
            l = mid + 1, ans = mid;
        else
            r = mid - 1;
    }
    printf("%lld", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/liuwenyao/p/11222416.html