BZOJ5281: [Usaco2018 Open]Talent Show(01分數規劃&DP)
阿新 • • 發佈:2018-11-14
性價比 只需要 ron true 等於 div 獲得 大於 ref
Submit: 166 Solved: 124
[Submit][Status][Discuss]
輸入的第一行包含N和W。下面N行,每行用兩個整數wi和ti描述了一頭奶牛。
1≤N≤250
1≤W≤1000
1≤wi≤10^6
1≤ti≤10^3
20 21
10 11
30 31
在這個例子中,總體來看最佳的才藝與重量的比值應該是僅用一頭才藝值為11、重量為10的奶牛,但是由於我們需
要至少15單位的重量,最優解最終為使用這頭奶牛加上才藝值為21、重量為20的奶牛。這樣的話才藝與重量的比值
為(11+21)/(10+20)=32/30=1.0666666...,乘以1000向下取整之後得到1066。 思路:分子分母的最大形式顯然需要二分後01分數規劃求最大。 二分到mid的時候,我們按照t-w*mid排序。 這個時候出現問題了,我們是選擇最前面幾個直到體積大於等於W嗎,顯然不是的。 比如需要體積W=120的東西,現在有三種(w,t):(100,100),(70,35),(20,9); 顯然選擇1,3的比值比選擇1,2搞,盡管2的性價比比3高。 主要是因為我們只需要W=120,2的性價比雖然高於3,但是無用的w也多了,拉低了整體性價比。
5281: [Usaco2018 Open]Talent Show
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 166 Solved: 124
[Submit][Status][Discuss]
Description
FarmerJohn要帶著他的N頭奶牛,方便起見編號為1…N,到農業展覽會上去,參加每年的達牛秀!他的第i頭奶牛重 量為wi,才藝水平為ti,兩者都是整數。在到達時,FarmerJohn就被今年達牛秀的新規則嚇到了: (一)參加比賽的一組奶牛必須總重量至少為W (這是為了確保是強大的隊伍在比賽,而不僅是強大的某頭奶牛),並且 (二)總才藝值與總重量的比值最大的一組獲得勝利。 FJ註意到他的所有奶牛的總重量不小於W,所以他能夠派出符合規則(一)的隊伍。幫助他確定這樣的隊伍中能夠 達到的最佳的才藝與重量的比值。Input
Output
請求出Farmer用一組總重量最少為W的奶牛最大可能達到的總才藝值與總重量的比值。 如果你的答案是A,輸出1000A向下取整的值,以使得輸出是整數 (當問題中的數不是一個整數的時候,向下取整操作在向下舍入到整數的時候去除所有小數部分)。Sample Input
3 1520 21
10 11
30 31
Sample Output
1066在這個例子中,總體來看最佳的才藝與重量的比值應該是僅用一頭才藝值為11、重量為10的奶牛,但是由於我們需
為(11+21)/(10+20)=32/30=1.0666666...,乘以1000向下取整之後得到1066。 思路:分子分母的最大形式顯然需要二分後01分數規劃求最大。 二分到mid的時候,我們按照t-w*mid排序。 這個時候出現問題了,我們是選擇最前面幾個直到體積大於等於W嗎,顯然不是的。 比如需要體積W=120的東西,現在有三種(w,t):(100,100),(70,35),(20,9); 顯然選擇1,3的比值比選擇1,2搞,盡管2的性價比比3高。 主要是因為我們只需要W=120,2的性價比雖然高於3,但是無用的w也多了,拉低了整體性價比。
#include<bits/stdc++.h> using namespace std; const int maxn=1010; struct in{ int w,t; double xjb; friend bool operator <(in w,in v){ return w.xjb>v.xjb; } }s[maxn];int N,W; double dp[maxn]; bool check(double Mid) { for(int i=1;i<=N;i++) s[i].xjb=(double)s[i].t-Mid*s[i].w; sort(s+1,s+N+1); for(int i=1;i<=W;i++) dp[i]=-1000000000.0; dp[0]=0.0; for(int i=1;i<=N;i++){ for(int j=W;j>=0;j--){ if(j+s[i].w>=W){ if(dp[j]+s[i].xjb>=0) return true; } else dp[j+s[i].w]=max(dp[j+s[i].w],dp[j]+s[i].xjb); } } return false; } int main() { scanf("%d%d",&N,&W); for(int i=1;i<=N;i++) scanf("%d%d",&s[i].w,&s[i].t); double L=0,R=1000000.0,Mid,ans=111; int num=100; while(num--){ Mid=(L+R)/2; if(check(Mid)) L=Mid,ans=L; else R=Mid; } printf("%d\n",(int)(ans*1000)); return 0; }
BZOJ5281: [Usaco2018 Open]Talent Show(01分數規劃&DP)