PAT 甲级 1068 Find More Coins

Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each bill, she must pay the exact amount. Since she has as many as 104 coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find some coins to pay for it.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive numbers: N (≤104, the total number of coins) and M (≤102, the amount of money Eva has to pay). The second line contains N face values of the coins, which are all positive numbers. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the face values V1≤V​2≤⋯≤Vk such that V1+V2+⋯+Vk=M. All the numbers must be separated by a space, and there must be no extra space at the end of the line. If such a solution is not unique, output the smallest sequence. If there is no solution, output “No Solution” instead.

Note: sequence {A[1], A[2], …} is said to be “smaller” than sequence {B[1], B[2], …} if there exists k≥1 such that A[i]=B[i] for all i

Sample Input 1:

8 9
5 9 8 7 2 3 4 1

Sample Output 1:

1 3 5

Sample Input 2:

4 8
7 2 4 3

Sample Output 2:

No Solution

算法策略
1、首先肯定是将数组排序,因为M的大小在100以内,每一个硬币都是一个正整数,所有大于100的硬币显然是没用的,可以不统计,我使用 数组cnt 统计每一个100以内数的数量,这样也就算排了序了吧。
2、下一步,模拟人脑,你想一下你会怎么算!!!

for example 我直接将第二行数有序摆放了(第二行是随机的序列)

20 9
1 2 2 3 4 5 7 8 9 10 11 12 12 13 13 16 17 18 19 20

以上是序列,要求硬币之和是9,这道题给有面额大于9的硬币,显然不在计算范围之内,因此从10到20这么多硬币根本不在计算范围之内。
硬币剩下了 1 2 2 3 4 5 7 8 9
首先选择硬币1,然后剩余的钱应该是8,那么硬币9就不在考虑范围内了。
1、选择 1 ,vector<1>,剩余8;
2、选择 2 ,vector<1 2>,剩余6;
3、选择 2,vector<1 2 2>,剩余4;
4、选择 3,vector<1 2 2 3>,剩余1;下一步要选择的硬币面额大于剩余,因此这条路不行,3出容器,回溯
5、选择 4,vector<1 2 2 4> 剩余0,说明成功,并且是这道题的最小的解,因为我的算法就是逐步尝试最小解的过程。

显然这就是枚举回溯的过程dfs深度优先搜索,把握好当前位置,和剩余,合理剪枝,计算量大大缩小。
以下见菜狗本菜狗的代码

/**
* Copyright(c)
* All rights reserved.
* Author : csdn写完这道题就睡觉
* Date : 2019-07-29-11.25.30
* Description : JZU PAT test
*/
#include
#include
#include
using namespace std;
int cnt[101]={0};
bool flag=false;  //如果找到了解,那么flag为true
void dfs(int curr,int left,vector<int>& v) // curr当前位置,left剩余
{
	if(left==0) //结束 
	{
			printf("%d",v[0]);
		for(int i=1;i<v.size();i++)
			printf(" %d",v[i]);
		printf("\n");
		flag=true;	
		return;
	}
	if(curr>left||flag) //下一步要尝试加的数已经大于了需要余数,失败;
	//或者flag为真,表示已经找到了最优解,所有的计算全部可以停止了。 
		return;	
	int i=0;
	for(i=curr;i<=left&&!flag;i++) //此处的flag是一个道理
		if(cnt[i]>0)
		{
			v.push_back(i);
			cnt[i]--;
			dfs(i,left-i,v); 
			cnt[i]++; //此处是回溯的过程
			v.pop_back();
		}
}
int main(){
    int n,m,t;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
    	scanf("%d",&t);
    	if(t<=100) //大于100面值的硬币是没有用处的,直接丢了。
    	cnt[t]++;
    }
	vector<int> ans;
	dfs(1,m,ans); //只在1 m内寻找,大于m的硬币显然是没用的  
	if(!flag)
		printf("No Solution\n");
    return 0;
}

你可能感兴趣的:(PAT,OJ试题)