CF1458B Glass Half Spilled
CF1458B Glass Half Spilled
題意:
有n杯水,第i杯有容積aia_{i}ai?單位,初始時裝有bib_{i}bi?單位的水
現在你可以進行若干次操作,每次選擇一杯水的一定水量并倒到另一杯水中,但是因為這些杯子形狀非常奇怪,因此每倒一次水,倒的水會有一半灑在地上.
求出對于所有整數p滿足1<=p<=n1<=p<=n1<=p<=n,求出進行若干次操作后選取p個杯子能獲得水單位數量的最大值
題解:
每次倒水都會有損失,那么倒水的過程肯定不能出現同樣的水來回倒,這樣必不優。因此我們就直接選中p個杯子,讓后將其他杯子里的水都倒進來。設選出的k個杯子的a值和為A且b值和為B,所有杯子的b值和為sumb。可以得到答案min{A,(sumb-B) * 0.5+B}=min{A,sumb * 0.5+B * 0.5}
現在我們就要求出對于每個A所對應的盡可能大的B(因為A是給出的,B不好求)
我們把A看作容積,把B看作價值,這不就是01背包,但本題A的容積不是固定的
A表示容積,而最多就100個杯子,每個杯子容積最大是100,也就是說A最大才10000,所以我們完全可以直接枚舉容積
因為題目問k個杯子的情況,所以我們還需要一維來記錄所選杯子數量
設dp[i][j]][k]:前i個杯子選了j個,且容積為k的最大價值(最大盛水容量)
我們可以通過滾動數組優化第一維
時間復雜度為O(n4)O(n^4)O(n4)
代碼:
#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime = clock ();freopen("data.in", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn=300; struct node{int a,b; }w[maxn]; int dp[102][10020]; int main() {//rd_test();int n;read(n);int sum=0;for(int i=1;i<=n;i++){cin>>w[i].a>>w[i].b;sum+=w[i].b;}memset(dp,-INF_int,sizeof dp);dp[0][0]=0;for(int i=1;i<=n;i++){for(int j=i;j>=1;j--){for(int k=10000;k>=w[i].a;k--){dp[j][k]=max(dp[j][k],dp[j-1][k-w[i].a]+w[i].b);}}}for(int i=1;i<=n;i++){double ans=0;for(int k=0;k<=10000;k++){ans=max(ans,1.0*min(1.0*k,0.5*sum+0.5*dp[i][k]));}printf("%.9lf ",ans); // cout<<ans<<endl;}return 0;//Time_test(); }總結
以上是生活随笔為你收集整理的CF1458B Glass Half Spilled的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 至尊蓝月安卓版(至尊蓝月安卓)
- 下一篇: 线性时间选择--用于解决第k大(小)元素