DAG-硬币问题

问题:有n种硬币,面值分别为V1,V2……Vn,每种都有无限多。给定非负整数s,可以选用多少个硬币,使得面值之和恰好为s?输出硬币数目最大值。

分析:这题依然是DP的入门题。先说说我在考虑时候的问题,第一就是刚开始认为硬币的值是状态,结果怎么想都想不通,第二就是在看紫书时对于他提出的通过赋一个非常小的初值以达到检验该路是否到达终点,一直想不通,最终在某汶神的帮助下才脱坑——这题确实挺水的= =。然后说下解题思路,本题的关键在于如何设置状态以及检测是否能够到达终点,前一个问题的解决办法就是设置面值和为状态,所以状态方式就为选择某个硬币,以当前面值和减去该硬币面值,得到新的面值和,即新的状态,第二个问题则需要将以面值和为下标的数组的下标为0的位置设置为0,其余设置为-1,并在DP时将状态设置为非常小的数,这样,当某路能够到达终点时,则可以取到0,并可以累加下去,而无法到达终点的路怎么无论怎么加都无法大于0

代码:

#include<cstdio>
#include<cstring>
int d[1000],v[10];
int max(int a, int b)
{
	return a > b ? a : b;
}
int dpmax(int s,int n)
{
	if (d[s] != -1)
		return d[s];
	d[s] = -10000;//用于设定不能走到终点的路肯定小于能走到终点的路
	for (int i = 0;i < n;i++)
		if (s >= v[i])//等号很关键
			d[s] = max(d[s], dpmax(s - v[i], n)+1);
	return d[s];
}

int main()
{
	int n, s, i;
	while (scanf("%d%d", &n, &s) != EOF)
	{
		for (i = 0;i < n;i++)
			scanf("%d", &v[i]);
		memset(d, -1, sizeof d);
		d[0] = 0;//用于辨别该路能否走到终点
		printf("%d\n", dpmax(s, n));
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值