第34題
(分?jǐn)?shù)背包)小 S 有 n 塊蛋糕,編號從 1 到 n。第 i 塊蛋糕的價值是 wi,體積是 vi。他有一個大小為 B 的盒子來裝這些蛋糕,也就是說裝入盒子的蛋糕的體積總和不能超過 B。
他打算選擇一些蛋糕裝入盒子,他希望盒子里裝的蛋糕的價值之和盡量大。
為了使盒子里的蛋糕價值之和更大,他可以任意切割蛋糕。具體來說,他可以選擇一個 α(0<α<1),并將一塊價值是 w,體積為 v 的蛋糕切割成兩塊,其中一塊的價值是 αw,體積是 αv,另一塊的價值是 (1?α)w,體積是 (1?α)v。他可以重復(fù)無限次切割操作。
現(xiàn)要求編程輸出最大可能的價值,以分?jǐn)?shù)的形式輸出。
比如 n=3,B=8,三塊蛋糕的價值分別是 4、4、2,體積分別是 5、3、2。
那么最優(yōu)的方法就是將體積為 5 的蛋糕切成兩份,一份體積是 3,價值是 2.4,另一份體積是 2,價值是 1.61,然后把體積是 3 的那部分和后兩塊蛋糕打包進盒子。最優(yōu)的價值之和是 8.4,故程序輸出 42/5。
輸入的數(shù)據(jù)范圍為:1≤n≤1000,1≤B≤105,1≤wi,vi≤100。
提示:將所有的蛋糕按照性價比 wi/vi 從大到小排序后進行貪心選擇。
試補全程序。
#include <cstdio>
using namespace std;
const int maxn = 1005;
int n, B, w[maxn], v[maxn];
int gcd(int u, int v) {
if (v == 0)
return u;
return gcd(v, u % v);
}
void print(int w, int v) {
int d = gcd(w, v);
w = w / d;
v = v / d;
if (v == 1)
printf("%d\n", w);
else
printf("%d/%d\n", w, v);
}
void swap(int &x, int &y) {
int t = x; x = y; y = t;
}
int main() {
scanf("%d %d", &n, &B);
for (int i = 1; i <= n; i ++) {
scanf("%d%d", &w[i], &v[i]);
}
for (int i = 1; i < n; i ++)
for (int j = 1; j < n; j ++)
if ( ① ) {
swap(w[j], w[j + 1]);
swap(v[j], v[j + 1]);
}
int curV, curW;
if ( ② ) {
③
} else {
print(B * w[1], v[1]);
return 0;
}
for (int i = 2; i <= n; i ++)
if (curV + v[i] <= B) {
curV += v[i];
curW += w[i];
} else {
print( ④ );
return 0;
}
print( ⑤ );
return 0;
}
① 處應(yīng)填( )