PAT_1068. Find More Coins

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
int M,N,a[10005],vis[10005],co=0;
bool hasFind = false;
void dfs(int sum,int start)
{
	if(sum==M)
	{
		hasFind=true;
		for(int i=0;i<N;i++)
			if(vis[i]==1)
			{
				if(co==0)
				{
					printf("%d",a[i]);
					co++;
				}
				else
					printf(" %d",a[i]);
			}
	}
	for(int i=start;i<N&&hasFind==false;i++)
	{
		if(vis[i]==1)
			continue;
		if(sum+a[i]>M)
			break;
		sum+=a[i];
		vis[i]=1;
		dfs(sum,i);
		sum-=a[i];
		vis[i]=0;
	}
}
int main()
{
	memset(vis,0,sizeof(vis));
	scanf("%d%d",&N,&M);
	for(int i=0;i<N;i++)
		scanf("%d",&a[i]);
	sort(a,a+N);
	dfs(0,0);
	if(hasFind==false)
		printf("No Solution");
	return 0;
}

 

最后一个点被卡时间了,我的想法是给输入的数列从小到大排个序,然后从最小的数开始深搜,一旦找到某个解,他一定就是最优解,因为

我是从最小的值开始深搜的,每次深搜找到的也是次小的值,所以一定能保证在有多个序列解的情况下,第一个找出来的序列,序列前部与

其他次优解的前部相等的情况下,第一个不等的值一定是最小的,也就达到了题目的要求。

但是这种解法在最坏情况,也就是无解的情况时间复杂度为O(2^N),每个节点都有选与不选两种情况。。。因此时间复杂度为2^N次,剪

枝只能改变较好情况下的时间复杂,但最坏情况,也就是无解的情况,时间复杂度过大。

到这里,我就考虑一下最坏情况 大概是哪些情况,试了一下当所有的输入值加起来 还没有 M大时,我们就不需要去做深搜了,因为不管怎么

加,都是无解的。。在代码里加入这一段判定之后就过了。。。


#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
int M,N,a[10005],vis[10005],co=0;
bool hasFind = false;
void dfs(int sum,int start)
{
	if(sum==M)
	{
		hasFind=true;
		for(int i=0;i<N;i++)
			if(vis[i]==1)
			{
				if(co==0)
				{
					printf("%d",a[i]);
					co++;
				}
				else
					printf(" %d",a[i]);
			}
	}
	for(int i=start;i<N&&hasFind==false;i++)
	{
		if(vis[i]==1)
			continue;
		if(sum+a[i]>M)
			break;
		sum+=a[i];
		vis[i]=1;
		dfs(sum,i);
		sum-=a[i];
		vis[i]=0;
	}
}
int main()
{
	int temp=0;
	memset(vis,0,sizeof(vis));
	scanf("%d%d",&N,&M);
	for(int i=0;i<N;i++)
	{
		scanf("%d",&a[i]);
		temp+=a[i];
	}
	if(temp<M)
		printf("No Solution");
	else
	{
		sort(a,a+N);
		dfs(0,0);
		if(hasFind==false)
			printf("No Solution");
	}
	return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值