1. 程式人生 > >Poj-2976 Dropping tests-01分數規劃

Poj-2976 Dropping tests-01分數規劃

問題描述:
In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be

Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.
Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is .

However, if you drop the third test, your cumulative average becomes
題目大意:
給出若干次考試的成績,對於一次考試,a為做對的題目數,b為總的題目數。求出所有n-k次考試中最大的平均成績
AC程式碼:

const int Mod = 100003;
int n,k;
int a[1010],b[1010];
double y[1010];
bool cmp(const double &a,const double &b)
{
    return a > b;
}
bool check(double x)
{
    for
(int i = 1; i <= n; ++i)//計算出v-x*w y[i] = a[i] - x * b[i]; sort(y + 1,y + n + 1,cmp);//由大到小排序 double sum = 0; for(int i = 1; i <= n - k; ++i)//求和 sum += y[i]; return sum >= 0;//判定 } int main() { while(cin >> n >> k) { if(n == 0 && k == 0
) break; for(int i = 1; i <= n; ++i) cin >> a[i]; for(int i = 1; i <= n; ++i) cin >> b[i]; double l = 0,r = 1;//二分的左右邊界 while(l + 1e-6 < r)//實數上的二分 { double mid = (l + r) / 2; if(check(mid) == true) l = mid; else r = mid; } printf("%.0lf\n",100 * l);//輸出四捨五入後的答案 } return 0; }

解決方法:
平均值最大化問題是經典的用二分答案法來求解的題型
通過二分答案,將求值轉為判定,降低了難度。
模型:
有n個物品的重量和價值分別是wi和vi,從中選出k個物品使得單位重量的價值最大
即求

max iSviiSwi
選與不選對應著1和0,所以這個問題也被稱為01分數規劃
單調性的簡單證明:
對於問題的答案ANS,設 VAL>ANS ,不可能有k個物品的選擇方案使得單位重量的價值為VAL;若 VAL<ANS ,則存在k個物品的選擇方案使得使得單位重量的價值大於等於VAL。
假如把k個物品的選擇方案看做函式的輸入,其單位重量的價值看做函式的輸出,則該函式是具有如上特殊的單調性
我們要做的就是通過二分找出最終答案這個分界點
判定函式: check(x) = true,存在k個物品的選擇方案使得其單位重量的價值 x
假設我們選擇了某個物品的集合S,它們單位重量的價值是 iSviiSwi
判斷是否存在S滿足 iSviiSwix
變形得到 iS(vixwi)0
因此就變成了 check(x) = (vi - x * wi)從大到小排列中的前k個數的和大於等於0
由於每次判斷需要快排,所以判斷的時間複雜度為O(nlogn)