NYOJ 914 Yougth的最大化

2021-06-23 03:25:00 字數 1592 閱讀 3064

時間限制:

1000 ms  |  記憶體限制:

65535 kb

難度:4 描述

yougth現在有n個物品的重量和價值分別是wi和vi,你能幫他從中選出k個物品使得單位重量的價值最大嗎?

輸入

有多組測試資料

每組測試資料第一行有兩個數n和k,接下來一行有n個數wi和vi。

(1<=k=n<=10000) (1<=wi,vi<=1000000)

輸出輸出使得單位價值的最大值。(保留兩位小數)

樣例輸入

3 2

2 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 輸出輸出使得單位價值的最大值。保留兩位小數 樣...