纪念品题解

该博客介绍了如何解决洛谷P5662题目,关键在于理解纪念品可以以金币或物品形式存在,目标是最大化最后的金币数量。通过深度优先搜索(DFS)策略,博主构建了转移方程,并提供了DFS函数的代码实现,讨论了如何在多天内持续优化金币收益。

题目

https://www.luogu.org/problem/P5662

思路

1.题目中有一句话

每天卖出纪念品换回的金币可以立即用于购买纪念品,当日购买的纪念品也可以当日卖出换回金币。当然,一直持有纪念品也是可以的。

看上去是一个句废话,其实在提示我们,一个物品可以以金币的形式存在我们的口袋里,也可以以物品的形式存在我们的口袋里。那么我们为了方便编程用金币的形式存储物品是比较方便的。

2.题目最终要求的是最大的金币数量。所以每一天结束后的持有金币数量+持有物品价值最大,才能获得最后的最大呢?”。具体的我们可以从转移方程中看出来。

3.写出dfs函数

dfs(int day, int j, int money)

day: 第day天

j:第j个物品

money:手上剩余的钱数

return:在第day的第j~n个物品上,我还剩money元,我瞎买物品(可能不买),那么第二天能换回的最大金币数量是多少?

那么dfs的转移关系就出来了

dfs(int day, int j, int money) = 
    max(a[day+1][j]*c + dfs(day, j+1, money-a[day][j]*c));

c:买多少个

a[day+1][j] :第二天的物品j的价格

money-a[day][j]*c : 因为买了c个物品,所以钱数变少了

附上dfs函数代码

int dfs(int day, int j, int money){
	int temp = 0;
	int ans = 0;
	
	if(j > N)
	{
		return money;
	}
	
	if(dp[j][money] != 0)
	{
		return dp[j][money];
	}
	
	for(int c = 0; c <= 99999; c++)
	{
		if(money-a[day][j]*c >= 0)
		{
			ans = max(a[day+1][j]*c + dfs(day, j+1, money-a[day][j]*c), ans);
		}
		else
		{
			break;
		}
	}
	return dp[j][money] = ans;
}

因为这只是求第day天的代码,如果求一共T天的最大钱数,就要不停的调用dfs函数

UP(day, 1, T-1)
{
    memset(dp, 0, sizeof(dp));
    money = dfs(day, 1, money); // 每一天结束获得的最大钱数作为下一天的初始资金
}

完整代码

#include<bits/stdc++.h>
#define UP(i,x,y) for(int i=x; i<=y; i++)
using namespace std;

int b[100] = {0};
int a[101][101] = {0};
int T,N,M;
int ans = 0;
int dp[101][10001]={0};
int maxPrice[101] = {0};
int minPrice[101] = {0};
int book[101][100000];

int dfs(int day, int j, int money){
	int temp = 0;
	int ans = 0;
	
	if(j > N)
	{
		return money;
	}
	
	if(dp[j][money] != 0)
	{
		return dp[j][money];
	}
	
	for(int c = 0; c <= 99999; c++)
	{
		if(money-a[day][j]*c >= 0)
		{
			ans = max(a[day+1][j]*c + dfs(day, j+1, money-a[day][j]*c), ans);
		}
		else
		{
			break;
		}
	}
	return dp[j][money] = ans;
}



int main()
{
//	freopen("f.out", "w", stdout);
	scanf("%d %d %d",&T, &N, &M);
	memset(minPrice, 0x7f, sizeof(minPrice));
	UP(i, 1, T)
	{
		UP(j, 1, N) 
		{
			scanf("%d",&a[i][j]);
		}
	}
		
	int money = M;
	UP(day, 1, T-1)
	{
		memset(dp, 0, sizeof(dp));
		money = dfs(day, 1, money);
	}
	cout<<money;
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值