uva 165 卡住了一下午!

最近上网发现自己写的文章出现在很多人的博客上面,还不注明是转载,还是原创!面对这种行为我无力吐槽,转载还请注明出处。谢谢!

http://blog.csdn.net/monkeyduck

这道题题意不太好懂,说的是给定h和k两个数,h是邮票的张数,k是邮票面额的种类,h+k<=9。举例来说,h=3,k=2就是有最多可以选三张邮票,有两种面额的邮票可选,具体面值多少自己定,要求可以组成的面额必须是连续且最大。面额可以定为1块和3块,这样选3张可以组成1,2,3,4,5,6,7,9块的总面额,所以最大连续的值为7。同样可以定面额为1块和四块,这样可以组成1,2,3,4,5,6,8,9,12块,但连续的只能到6,所以h=3,k=2这种条件下7是最有解。

这个题最开始我是用的回溯套回溯的办法,因为面额要枚举,然后每一张怎么选也要枚举,但这样非常慢,后来参考网上别人的做法,先枚举在现有邮票的情况下可以达到的最大连续面额,然后枚举面额,每往后枚举一位的下限是前一位的面额+1,上限是之前的连续和的最大值+1。

#include<iostream>
#include<cstring>
#include<iomanip>

using namespace std;

int h,k,Maxsum,Put[10],De[10],finalDe[10];
bool vis[200];

void getsum(int n,int cur,int sum)			//在现有邮票情况下的面额
{
	if (cur==h)
	{
		vis[sum]=1;
		return;
	}
	vis[sum]=1;
	for (int i=0;i<=n;i++)
		getsum(n,cur+1,sum+De[i]);
	
}
void dfs(int cur,int num)
{
	if (cur==k+1)
	{
		if (num-1>Maxsum)
		{
			Maxsum=num-1;
			memcpy(finalDe,De,sizeof(De));
		}
	}
	else
	{
		for (int i=De[cur-1]+1;i<=num;i++)
		{
			De[cur]=i;
			memset(vis,0,sizeof(vis));
			getsum(cur,0,0);	//为了标记vis数组得到下一次枚举面额的上限j
			int j=De[cur-1]+1;
			while(vis[j++])
				;
			dfs(cur+1,j-1);		//j-1即为之前的面额无法达到的值,下一次枚举的面额不能超过此致,否则会出现断点

		}
	}
}

int main()
{
	while (cin>>h>>k&&h)
	{
		Maxsum=0;
		De[0]=0;
		De[1]=1;
		dfs(2,h+1);
		for (int i=1;i<=k;i++)
			cout<<setw(3)<<finalDe[i];
		cout<<" ->";
		cout<<setw(3)<<Maxsum<<endl;
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值