捡硬币问题 动态规划算法C语言实现

问题描述:

现有n个硬币按顺序依次排列在你面前,它们的面值可以看作一个数组coins[]={5,1,2,10,6,2},请在此中选取若干个硬币,使得所取硬币面值总和最大,捡取个数不限,但相邻的硬币不能捡取,请设计相应算法,要求能够输出累加值和选取的硬币序号(硬币面值为正数)

提示:建立数组dp[i]存储选取前i个硬币的累加值

#include<stdio.h>
#include<stdlib.h>
#define N 6
int j=0;
int selectcoins(int c[],int n,int s[])
{
	int i,dp[n];
	dp[0]=0;
	dp[1]=c[0];
	s[j]=1;//因为dp[1]=c[0],暂时选择了第一个硬币,所以暂时给s[0]赋值为1 
	for(i=2;i<=n;i++)
	{
		if(dp[i-2]+c[i-1]>dp[i-1])
		{
			dp[i]=dp[i-2]+c[i-1];
			if(s[j]==i-1) j--;//注意s[j]被赋值后值还可能会变,当满足这种情况时,s[j]会被再次赋值,即新的值覆盖原来的值 
			s[++j]=i;//记录选取硬币的序号 
		}	
		else
		{
			dp[i]=dp[i-1];//这种情况不需要记录新的硬币序号,因为此时dp[i]选取的硬币情况和dp[i-1]一样 
		}
	}
	return dp[--i];//i最后跳出循环时多加了一次1,故还要减一 
} 
int main()
{
	int coins[N]={5,1,2,10,6,2};
	int s[N/2+1]={0};//该数组用来存储选择的硬币序号,因为最多选择N/2+1项,所以数组大小为N/2+1 
	int max,i;
	max=selectcoins(coins,N,s);
	printf("max=%d\n",max);
	printf("选取的硬币编号为:");//硬币编号从1开始 
	for(i=0;i<=j;i++)//输出硬币编号,注意此处是i<=j,而不是i<N,表示后面未被赋值的s[j]不输出 
		printf("%d ",s[i]);
	return 0; 
}

运行结果 

 这只是针对一个具体的问题,读者可根据具体问题设置具体参数(代码是自己想的,还有很多可优化之处,后续作者会在空余时间优化代码,以适应更多问题场景,欢迎各位大佬提出宝贵建议。爱你们哦,嘿嘿)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值