Codeforces Round #691 (Div. 2) D. Glass Half Spilled
阿新 • • 發佈:2020-12-27
題意:n個杯子,容量ai,已有bi的水。每次往其他杯子倒水會損失倒出水一半,問你最終只留k個杯子有水,其他杯子的水都往這k個杯子裡倒,問每個k最終保留的水最大是多少。
做法:通過揹包去求對於一個容量A,當此時選取留下k個杯子時,這k個杯子的最大容量是多少(直接揹包即可)
然後再對於每一個k,列舉容量(選不同的杯子導致容量不同,所以需要全部列舉),去統計把剩下所有水倒入這個容量後的最大值,再輸出 0.5 * (sumb - dp[i][j])+dp[i][j],其中sumb-dp[i][j]為要倒出去的水。
#include<bits/stdc++.h> using namespace std; #define ll unsigned long long #define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL) const int maxn = 1e5 + 10; int a[110], b[110], dp[110][110 * 110]; int main() { fastio; int n; cin >> n; memset(dp, -1, sizeof(dp)); dp[0][0] = 0; int suma = 0, sumb = 0; for (int i = 1; i <= n; i++)cin >> a[i] >> b[i], suma += a[i], sumb += b[i]; //先去找對於一個容量A,一開始選k個能夠擁有最多水的組合(其實就是一個揹包) for (int i = 1; i <= n; i++) for (int k = i; k; k--)//k和A都需要倒著列舉 for (int A = suma; A >= a[i]; A--) if (~dp[k - 1][A - a[i]])//從合法狀態轉移 dp[k][A] = max(dp[k][A], dp[k - 1][A - a[i]] + b[i]); //統計答案 for (int i = 1; i <= n; i++) { double ans = 0; for (int j = 1; j <= suma; j++) if(~dp[i][j]) ans = max(ans, min(1.0 * j, 0.5 * (sumb + dp[i][j]))); cout << fixed << setprecision(10) << ans << " "; } return 0; }