HDU 3236 Gift Hunting(0-1背包变异)

本文介绍了一个特定条件下为女友挑选礼物的问题,通过使用两张不同价值的优惠券及一次免费获取机会,来最大化女友的幸福感。该问题可以转化为一种0-1背包问题的变种,并通过动态规划求解。

Gift Hunting

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1743    Accepted Submission(s): 581


Problem Description
After winning two coupons for the largest shopping mart in your city, you can't wait inviting your girlfriend for gift hunting. Having inspected hundreds of kinds of souvenirs, toys and cosmetics, you finally narrowed down the candidate list to only n gifts, numbered 1 to n. Each gift has a happiness value that measures how happy your girlfriend would be, if you get this gift for her. Some of them are special - you must get it for your girlfriend (note that whether a gift is special has nothing to do with its happiness value).

Coupon 1 can be used to buy gifts with total price not greater than V1 (RMB). Like most other coupons, you can’t get any money back if the total price is strictly smaller than V1. Coupon 2 is almost the same, except that it’s worth V2. Coupons should be used separately. That means you cannot combine them into a super-coupon that’s worth V1+V2. You have to divide the gifts you choose into two part, one uses coupon 1, the other uses coupon 2.

It is your girlfriend's birthday today. According to the rules of the mart, she can take one (only one) gift for FREE! Here comes your challenge: how to make your girlfriend as happy as possible?
 

Input
There will be at most 20 test cases. Each case begins with 3 integers V1, V2 and n (1 <= V1 <= 500, 1 <= V2 <= 50, 1 <= n <= 300), the values of coupon 1 and coupon 2 respectively, and the number of candidate gifts. Each of the following n lines describes a gift with 3 integers: P, H and S, where P is the price, H is the happiness (1 <= P,H <= 1000), S=1 if and only if this is a special gift - you must buy it (or get it for free). Otherwise S=0. The last test case is followed by V1 = V2 = n = 0, which should not be processed.
 

Output
For each test case, print the case number and the maximal total happiness of your girlfriend. If you can't finish the task, i.e. you are not able to buy all special gifts even with the 1-FREE bonus, the happiness is -1 (negative happiness means she's unhappy). Print a blank line after the output of each test case.
 

Sample Input
3 2 4 3 10 1 2 10 0 5 100 0 5 80 0 3 2 4 3 10 1 2 10 0 5 100 0 5 80 1 0 0 0
 

Sample Output
Case 1: 120 Case 2: 100



题意:有两张优惠券分别为v1,v2,和一次免费特权,你女朋友生日,问你用以上条件去退换礼物,每个礼物有一定的幸福指数,且有些礼物你必须买,如果特殊礼物不能全买输出-1,否则输出你能为你女朋友买到的最大的幸福指数。


解题思路:

每个物品只有两种选择方案,买或者不买,所以一想到是0-1背包,但是这题不是纯背包,是背包的变异。我们可以这样想,用两张优惠券分别去购买(并行着),假设dp[0,1][v1][v2],0表示还没有用免费机会,1 表示用了免费的机会,那么dp[0][v1][v2] 表示花了v1,v2还没使用免费的机会获得的最大的幸福指数,dp[1][v1][v2]表示用了免费的机会获得的最大的幸福指数。最后只要判断dp[1][v1][v2]是否大于0即可。


详细见代码:

<span style="font-size:18px;"> #include<iostream>
 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 #include<cmath>
 #define INF 0x3f3f3f3
 using namespace std;
 int dp[2][505][55];
 int p[310],h[310],s[310];
 int main()
 {
     int v1,v2,n,cas=0;
     while(~scanf("%d %d %d",&v1,&v2,&n) && v1+v2+n){
        for(int i=1;i<=n;i++){
            scanf("%d %d %d",&p[i],&h[i],&s[i]);
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
            int w=p[i],v=h[i];
            for(int j=v1;j>=0;j--){
                for(int k=v2;k>=0;k--){
                    int ans=dp[0][j][k];
                    if(s[i]==0){
                        dp[1][j][k]=max(dp[1][j][k],ans+v);
                        if(j>=w){
                            dp[0][j][k]=max(dp[0][j][k],dp[0][j-w][k]+v);
                            dp[1][j][k]=max(dp[1][j][k],dp[1][j-w][k]+v);
                        }
                        if(k>=w){
                            dp[0][j][k]=max(dp[0][j][k],dp[0][j][k-w]+v);
                            dp[1][j][k]=max(dp[1][j][k],dp[1][j][k-w]+v);
                        }
                    }
                    else{
                        dp[1][j][k]=ans+v;
                        if(j>=w && k>=w){
                            dp[0][j][k]=max(dp[0][j][k-w],dp[0][j-w][k])+v;
                            dp[1][j][k]=max(dp[1][j][k-w],dp[1][j-w][k])+v;
                        }
                        else if(j>=w){
                            dp[0][j][k]=dp[0][j-w][k]+v;
                            dp[1][j][k]=max(dp[1][j-w][k]+v,dp[1][j][k]);
                        }
                        else if(k>=w){
                            dp[0][j][k]=dp[0][j][k-w]+v;
                            dp[1][j][k]=max(dp[1][j][k-w]+v,dp[1][j][k]);
                        }
                        else dp[0][j][k]=-INF;
                    }
                }
            }
        }
        printf("Case %d: %d\n\n",++cas,dp[1][v1][v2]<0 ? -1 : dp[1][v1][v2]);
     }
     return 0;
 }
</span>


内容概要:本文提出了一种基于非合作博弈理论的居民负荷分层调度模型,并结合双层鲸鱼优化算法(Two-level Whale Optimization Algorithm)进行高效求解,模型与算法均通过Matlab代码实现。研究针对电力系统中居民侧用电负荷的复杂调度问题,引入非合作博弈机制刻画各用户之间的利益竞争关系,实现负荷的分层优化分配;同时设计双层优化架构,上层优化资源配置,下层模拟用户自主决策行为,提升了模型的实用性与合理性。通过智能优化算法求解多层级、非凸非线性的博弈模型,有效提高了调度方案的收敛性与全局寻优能力,适用于现代智能电网中的需求侧管理与能源优化场景。; 适合人群:具备电力系统基础理论知识和Matlab编程能力,从事智能电网、能源优化调度、需求侧管理、博弈论应用等方向的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①应用于居民区电力负荷的分层优化调度系统设计与仿真分析;②为非合作博弈在多主体能源系统建模中的应用提供方法论支持;③利用双层鲸鱼算法解决具有嵌套结构的复杂双层优化问题,提升求解效率与调度方案的可行性。; 阅读建议:建议读者结合提供的Matlab代码深入理解模型构建逻辑与算法实现流程,重点关注博弈模型的效用函数设计、纳什均衡求解思路以及双层优化结构的迭代机制,宜配合实际用电数据开展复现实验以验证模型有效性与鲁棒性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值