UESTC 1606 难喝的饮料 0-1背包+完全背包

117 篇文章 2 订阅
12 篇文章 0 订阅

难喝的饮料

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit  Status
title

title
图文无关


wdk喜欢跑步,每天晚上他都要跑上半小时。跑得大汗淋漓后,他不得不喝点饮料补充水分。
饮料有两大类,一类是饮用水,可以无限取用。一类是苏打水,每种只有一瓶。
wdk不喜欢喝饮料,每喝一瓶饮料他的难受程度就上升bi。他不想难受得满地打滚,所以他不会让自己的难受程度高于K。
每瓶饮料可以补充水分ai。此外,wdk是个有始有终的人,他要么喝下一整瓶水,要么不喝。
现在wdk想问问你他最多能补充多少水分呢?


Input

第一行两个数1<=n<=2×10^4和0<=K<=10^4,表示一共有n种饮料,难受阙值为K。
接下来n行,每行三个数t,0<=a<=10^4,0<b<=10^4,a,b含义同题意,t=1表示是饮用水,t=2表示是苏打水。

Output

一个数,表示最多补充的水分。

Sample input and output
Sample Input Sample Output
3 10                                 6
1 3 5
2 4 6

1 2 3


Hint

良心出题人!test1 为样例! (然而最极端的数据在41和42)


Source

2017 UESTC Training for Dynamic Programming

UESTC 1606 难喝的饮料

My Solution

0-1背包+完全背包
通过递推顺序,第一维可以直接省略
for(i = 1; i <= n; i++){
   if(c[i]){//0-1背包
        for(j = w; j >= 0; j--){
            if(j - need[i] >= 0) dp[j] = max(dp[j], dp[j-need[i]] + value[i]);
            else break;
        }
    }
    else{//完全背包
        for(j = 0; j <= w; j++){
            if(j - need[i] >= 0) dp[j] = max(dp[j], dp[j-need[i]] + value[i]);
        }
    }
}
时间复杂度 O(n*k)
空间复杂度 O(k)


#include <iostream>
#include <cstdio>

using namespace std;
typedef long long LL;
const int MAXN = 2e4 + 8, MAXM = 1e4 + 8;

int need[MAXN], value[MAXN], dp[MAXM];
bool c[MAXN];

template <class T>
inline void cinn(T &ret)
{
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    ret=c-'0';
    while(c=getchar(),c>='0'&&c<='9')
        ret=ret*10+(c-'0');
}

int main()
{
    #ifdef LOCAL
    freopen("d.txt", "r", stdin);
    //freopen("d.out", "w", stdout);

    #endif // LOCAL
    //ios::sync_with_stdio(false); cin.tie(0);

    int n, w, t, i, j, k;
    //cin >> n >> w;
    //scanf("%d%d", &n, &w);
    cinn(n); cinn(w);
    for(i = 1; i <= n; i++){
        cinn(t); cinn(value[i]); cinn(need[i]);
        c[i] = t - 1;
    }
    for(i = 1; i <= n; i++){
        if(c[i]){
            for(j = w; j >= 0; j--){
                if(j - need[i] >= 0) dp[j] = max(dp[j], dp[j-need[i]] + value[i]);
                else break;
            }
        }
        else{
            for(j = 0; j <= w; j++){
                if(j - need[i] >= 0) dp[j] = max(dp[j], dp[j-need[i]] + value[i]);
            }
        }
    }

    //cout << dp[n-1][w] << endl;
    printf("%d\n", dp[w]);
    return 0;
}


  Thank you!

                                                                                                                                            ------from ProLights

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值