码迷,mamicode.com
首页 > 其他好文 > 详细

【CodeForces】 730J Bottles

时间:2018-02-23 00:45:18      阅读:327      评论:0      收藏:0      [点我收藏+]

标签:set   str   minimal   can   cond   顺序   01背包问题   into   cout   

传送门

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

标签:set   str   minimal   can   cond   顺序   01背包问题   into   cout   

原文地址:https://www.cnblogs.com/Fang-Hao/p/8460595.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!