時間限制:
1000 ms | 記憶體限制:
65535 kb
難度:4 描述
yougth現在有n個物品的重量和價值分別是wi和vi,你能幫他從中選出k個物品使得單位重量的價值最大嗎?
輸入
有多組測試資料
每組測試資料第一行有兩個數n和k,接下來一行有n個數wi和vi。
(1<=k=n<=10000) (1<=wi,vi<=1000000)
輸出輸出使得單位價值的最大值。(保留兩位小數)
樣例輸入
3 22 25 3
2 1
樣例輸出
0.75分析:
要想取得單位重量價值最大,需要在0-max之間二分搜尋,max為任意選物品所得的單位重量最大價值,
max = max(v[i] / w[i] | i = 0...n - 1)。
為什麼max如此取值,下面證明:
假設一對vi,wi 滿足: vi / wi = max(v[i] / w[i] | i = 0......n-1),任取一對 vk,wk (k != i),則有vi / wi > vk / wk,
即:vi * wk > vk * wi 把它記為公式1。
證明:要證的是 (vi + vk1 +...+ vk2) / (wi + wk1 +...+ wk2) <= vi / wi, (0<=k1<=k2<=n-1 && k1 != i && k2 != i),
1.當k1 = k2 = 0 時,即不增加,上式等號成立。
2.為便於證明,此處只增加vk(k != i),它具有普通性。即證(vi + vk) / (wi + wk) < vi / wi,
即wi(vi + vk) < vi(wi + wk),也就是vi * wk > vk * wi,此式即為公式1,成立!
3.當增加2......n-1 個數時也成立。
4.證畢。
對於cleck(a)若不理解見**下面詳解。
#include#include#include#includeusing namespace std;
const int maxn = 10000 + 5;
double x[maxn], w[maxn], v[maxn]; //全定義為double,便於計算
int n, k;
bool cleck(double a)
int main()
double l = 0, r = max;
while(r - l > 1e-4)
printf("%.2lf\n", l);
}return 0;
}
cleck(a)為檢查單位重量價值a是否可取,若可取,需滿足
(vk1 +...+ vk2) / (wk1 +...+ wk2) >= a (0<=k1<=k2<=n-1),
即vk1 +...+ vk2 >= a(wk1 +...+ wk2),
即vk1 - a * wk1 +...+ vk2 - a * wk2 >= 0
所以盡量取vki - a * wki(即**中xi)大的才有可能滿足。
NYOJ 914 Yougth的最大化
時間限制 1000 ms 記憶體限制 65535 kb 難度 4 描述 yougth現在有n個物品的重量和價值分別是wi和vi,你能幫他從中選出k個物品使得單位重量的價值最大嗎?輸入 有多組測試資料 每組測試資料第一行有兩個數n和k,接下來一行有n個數wi和vi。1 k n 10000 1 wi,v...
NYOJ 914 Yougth的最大化
題目資訊 時間限制 1000 ms 記憶體限制 65535 kb 難度 4 描述 yougth現在有n個物品的重量和價值分別是wi和vi,你能幫他從中選出k個物品使得單位重量的價值最大嗎?輸入 有多組測試資料 每組測試資料第一行有兩個數n和k,接下來一行有n個數wi和vi。1 k n 10000 1...
NYOJ914Yougth的最大化
描述 yougth現在有n個物品的重量和價值分別是wi和vi,你能幫他從中選出k個物品使得單位重量的價值最大嗎?輸入 有多組測試資料 每組測試資料第一行有兩個數n和k,接下來一行有n個數wi和vi。1 k n 10000 1 wi,vi 1000000 輸出輸出使得單位價值的最大值。保留兩位小數 樣...