• 洛谷 P4377 [USACO18OPEN]Talent Show + 分数规划


    分数规划

    分数规划可以用来处理有关分数即比值的有关问题。

    而分数规划一般不单独设题,而是用来和dp,图论,网络流等算法结合在一起。

    而基础的做法一般是通过二分。

    二分题目我们都知道,需要求什么的最小或最大值,就二分什么。

    而该最小或最大值都会满足单调性。

    设当前最大值为(maxn),如果存在比值使得比(maxn)大,则有(y/x>maxn),化简得:(y-x*maxn>0)

    就可以更新答案。所以满足二分性(即(maxn)越大则(y-maxn*x))越小则越难更新答案。

    而二分check可以通过排序求得(y[i]-x[i]*maxn)的最大值,然后直接贪心取最大值,最后判断是否大于0即可

    该题目

    而对于该题来说,贪心的话显然不能通过排序求最大值,因为还有一个重量限制,所以可以用背包。

    重量即为原数据的重量,价值即为(y[i]-x[i]*maxn),在转移时需要把所有重量大于W的最后都转移到W上

    最后方便统计。

    #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;
    }
    
  • 相关阅读:
    在UI上使用BackgroundWorker
    洛谷训练新手村之“洛谷的第一个任务”题解
    洛谷训练新手村之“循环!循环!循环!”题解
    洛谷训练新手村之“BOSS战入门综合练习1”题解
    洛谷训练新手村之“过程函数与递归”题解
    洛谷P1720 月落乌啼算钱 题解 斐波那契数列/特征方程求解
    洛谷训练新手村之“顺序与分支”题解
    洛谷训练新手村之“数组”题解
    [转]特征方程
    洛谷训练新手村之“简单字符串”题解
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11222416.html
Copyright © 2020-2023  润新知