hihoCoder184——满减优惠

题目1 : 满减优惠

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

最近天气炎热,小Ho天天宅在家里叫外卖。他常吃的一家餐馆一共有N道菜品,价格分别是A1, A2, ... AN元。并且如果消费总计满X元,还能享受优惠。小Ho是一个不薅羊毛不舒服斯基的人,他希望选择若干道不同的菜品,使得总价在不低于X元的同时尽量低。

你能算出这一餐小Ho最少消费多少元吗?

输入

第一行包含两个整数N和X,(1 <= N <= 20, 1 <= X <= 100)

第二行包含N个整数A1, A2, ..., AN。(1 <= Ai <= 100)

输出

输出最少的消费。如果小Ho把N道菜都买了还不能达到X元的优惠标准,输出-1。

好久没有写题了,不得不说csdn这个编辑页面真的是越改越差。

这道题我用了动规跟dfs做,结果dfs只有70分,我也不太懂,都po出来吧。动规好理解,就是01背包问题,这里再梳理一下这类型的问题。

01背包:动态规划之01背包问题(最易理解的讲解)

大概意思就是:f [ I, j ] = max { ( f [ i-1, j - Wi ] + Pi)(其中 j >= Wi ) , f [ I-1, j ] } :f代表背包里有 I 个物体,其重量为 j 时的价值,其中每个物品的重量为Wi,价值为Pi。一般遍历就是从 i : 0-->n,j :0 --> sum(Wi),(初始值都为零)也视情况而定。

int main(){
    int sum = 0;
    cin>>n>>x;
    int dp[200] = {0};
    
    for(int i = 0; i<n; i++){
        scanf("%d", &a[i]);
        sum += a[i];
    }
    
    int d = sum-x;
    if(d < 0) printf("-1\n");
    else if(d == 0) printf("%d\n", x);
    else{
        int out = -1;
        for(int i = 0; i<n; i++){
            for(int j = d; j>=0; j--){
                dp[j] = max(dp[j], dp[j-a[i]]+a[i]);
                out = max(dp[j], out);
            }
        }
        printf("%d", out);
    }
    return 0;
}

因为这个对物品的个数不敏感,所以不用dp[i,j],只用dp[i]即可。先将所有的物体全放进去,然后在物品总重大于x(d>0)的情况下能拿多少就拿多少。之前一直想着先动规出在总重小于x的时候拿到最大,然后再加上任意其他看最小,可行性很低,换个思路就简单多了。


dfs我也不知道哪里错了,就是排列组合的说。

int a[200] = {0};
int n, x;

int dfs(int b, int sum){
    int out = 1000000000;
    if(sum >= x){
        return sum;
    }
    for(int i = b+1; i<n; i++){
        out = min(out, dfs(i, sum+a[i]));
    }
    return out;
}

int _main() {
    int sum = 0;
    int out = 1000000000;
    cin>>n>>x;
    
    for(int i = 0; i<n; i++){
        scanf("%d", &a[i]);
        sum += a[i];
    }
    
    if(sum < x){
        printf("-1\n");
        return 0;
    }
    sort(a, a+n, [](int x1, int x2){return x1 < x2;});
    
    for(int i = 0; i<n; i++){
        out = min(out, dfs(i, a[0]));
    }
    printf("%d\n", out);
    return 0;  
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值