1. 程式人生 > >【CodeForces】 730J Bottles

【CodeForces】 730J Bottles

得到 ron possible reg clu std term more pen

傳送門

codeforces

luogu

題目描述

Nick has n bottles of soda left after his birthday. Each bottle is described by two values: remaining amount of soda ai and bottle volume bi (ai?≤?bi).

Nick has decided to pour all remaining soda into minimal number of bottles, moreover he has to do it as soon as possible. Nick spends x seconds to pour x units of soda from one bottle to another.

Nick asks you to help him to determine k — the minimal number of bottles to store all remaining soda and t — the minimal time to pour soda into k bottles. A bottle can‘t store more soda than its volume. All remaining soda should be saved.

思路

  首先發現最開始的一步肯定是貪心,按容量sort一遍可以得到第一個答案,然後稍微轉化一下題意,就可以發現,轉化後的提議是這個樣子:從n個瓶子裏面選出num個,使得這num個瓶子的容積之和要大於水的體積,並且當時間最短時,一定有這num個瓶子裏的水體積和最大,就可以發現是一個01背包問題。

  dp[i][j]表示選了i個瓶子,一共的容積為j的時候,這i個瓶子裏水的最大值。由此可得dp方程

            dp[j][k]=max(dp[j][k],dp[j-1][k-b[i].v]+b[i].r);

小細節

  差點被坑死在這裏,按照容量枚舉k的時候一定要倒著枚舉,不然就成完全背包了2333333。

  而且要註意枚舉的順序,最外層枚舉的是選第i個,然後枚舉容量,然後在枚舉選了多少個,這樣可以保證一個瓶子只選一次,不然會掛得很慘qwq

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include
<algorithm> using namespace std; struct nod{ int r; int v; }; nod b[105]; inline int cmp(nod x,nod y){ return x.v>y.v; } int dp[105][20000]; int main(){ int n; cin>>n; int rest=0; for(register int i=1;i<=n;i++){ cin>>b[i].r; rest+=b[i].r; } for(register int i=1;i<=n;i++){ cin>>b[i].v; } sort(b+1,b+n+1,cmp); memset(dp,-1,sizeof(dp)); dp[0][0]=0; int num=-1,tot=0; for(register int i=1;i<=n;i++){ tot+=b[i].v; if(tot>=rest&&num==-1)num=i; } cout<<num<<endl; for(register int i=1;i<=n;i++){ //xuan di ji ge for(register int k=tot;k>=b[i].v;k--){ for(register int j=1;j<=num;j++){ //xuan le ji ge if(dp[j-1][k-b[i].v]!=-1){ dp[j][k]=max(dp[j][k],dp[j-1][k-b[i].v]+b[i].r); //cout<<dp[j-1][k-b[i].v]<<‘ ‘<<b[i].r<<endl; //cout<<i<<‘ ‘<<j<<‘ ‘<<k<<endl<<endl; } } } } // while(1){ // int x,y; // cin>>x>>y; // cout<<dp[x][y]<<endl; // } int ans=-1; for(register int i=rest;i<=tot;i++){ ans=max(ans,dp[num][i]); } //cout<<tot<<endl; cout<<rest-ans<<endl; }

【CodeForces】 730J Bottles