回溯法
小F的超市购物策略
1.题目思路
利用深度优先搜索(DFS)算法来解决小F的超市购物策略问题,通过递归地探索所有可能的购买组合,同时遵守超市的优惠活动规则,即购买一个商品后下一个商品可以半价购买,但如果下一个商品半价,则再下一个商品必须原价购买。在遍历过程中,代码维护一个全局变量maxlove来记录找到的最大喜爱度总和,每次递归时都会尝试三种情况:以半价购买当前商品、以原价购买当前商品以及跳过当前商品,同时更新总花费和喜爱度总和。当遍历到达叶子节点或超出预算时,会回溯并尝试其他购买路径,最终返回在给定预算下能够获得的最大喜爱度总和。
2.详细方法
初始化: 定义一个全局变量maxlove,用来存储遍历过程中找到的最大喜爱度总和,初始值为0。
DFS函数:- 定义一个递归函数dfs,它尝试所有可能的购买组合,并在遍历过程中更新maxlove。
DFS逻辑:
- 终止条件:如果当前索引
i等于商品总数n,或者总花费t超过预算x,则终止递归。 - 回溯处理:如果
t超过x,说明最后购买的商品超出预算,需要撤销这次购买,即从love中减去该商品的喜爱度,从t中减去该商品的价格。 - 更新最大喜爱度:如果当前的喜爱度总和
love大于全局变量maxlove,则更新maxlove。
购买决策:
-
半价购买:如果上一个商品是原价购买的(
half为0),则当前商品可以半价购买。更新总花费t为t + a[i] / 2,更新喜爱度总和love为love + b[i],并将half标志设置为0,表示下一个商品必须原价购买。 -
原价购买:如果上一个商品是半价购买的(
half为1),或者当前商品不能半价购买,则以原价购买。更新总花费t为t + a[i],更新喜爱度总和love为love + b[i],并将half标志设置为1,表示下一个商品可以半价购买。 -
跳过购买:无论是否半价,都可以尝试跳过当前商品,不进行购买,保持
t和love不变,并将half标志设置为0。
更新最大喜爱度:在DFS遍历过程中,如果当前的喜爱度总和love大于全局变量maxlove,则更新maxlove。
返回结果:在solution函数中,返回maxlove的值,即在给定预算下能够获得的最大喜爱度总和。
3.代码实现
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include <functional>
using namespace std;
typedef long long int ll;
int maxlove=0;
void dfs(int i,int t,int love,int half,int n,int x,std::vector<int> a, std::vector<int> b){
if(i==n || t>x){
if(t>x){
love-=b[i-1];
t-=a[i-1];
}
if(love>maxlove){
maxlove=love;
return;
}
return ;
}
if(half==1){
dfs(i+1,t+a[i]/2,love+b[i],0,n,x,a,b);
}
else{
dfs(i+1,t+a[i],love+b[i],1,n,x,a,b);
dfs(i+1,t+a[i],love+b[i],0,n,x,a,b);
}
dfs(i+1,t,love,0,n,x,a,b);
}
int solution(int n, int x, std::vector<int> a, std::vector<int> b) {
// write code here
maxlove=0;
dfs(0,0,0,0,n,x,a,b);
//cout << maxlove << "\n";
return maxlove;
}
int main() {
std::cout << (solution(4, 7, {2, 2, 6, 2}, {3, 4, 5, 1}) == 12) << std::endl;
std::cout << (solution(3, 10, {4, 4, 4}, {2, 3, 5}) == 10) << std::endl;
std::cout << (solution(5, 8, {2, 4, 4, 6, 2}, {1, 2, 3, 4, 5}) == 10) << std::endl;
}