韩梅梅喜欢满宇宙到处逛街。现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债。韩梅梅手边有 104枚来自各个星球的硬币,需要请你帮她盘算一下,是否可能精确凑出要付的款额。
输入格式:
输入第一行给出两个正整数:N(≤104)是硬币的总个数,M(≤102 )是韩梅梅要付的款额。第二行给出 N 枚硬币的正整数面值。数字间以空格分隔。
输出格式:
在一行中输出硬币的面值 V1 ≤V2 ≤⋯≤Vk,满足条件 V1+V2+…+Vk=M。数字间以 1 个空格分隔,行首尾不得有多余空格。若解不唯一,则输出最小序列。若无解,则输出 No Solution。
注:我们说序列{ A[1],A[2],⋯ }比{ B[1],B[2],⋯ }“小”,是指存在 k≥1 使得 A[i]=B[i] 对所有 i<k 成立,并且 A[k]<B[k]。
输入样例 1:
8 9
5 9 8 7 2 3 4 1
输出样例 1:
1 3 5
输入样例 2:
4 8
7 2 4 3
输出样例 2:
No Solution
解题思路:
dfs深搜,关键是要打印路径和剪枝,我也处于学习时期,代码有参考。打印路径可以用一个数组储存起来,递归需要先选后不选,为什么还是自己想一下吧。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int a,b,c,d[10010],e[10010],flag=0,i,Sum[10010];
int dfs(int ans,int f,int sum)
{
if(ans==a+1)return 0;//剪枝,如果找到了,总数超出了,或者加上后面的数都达不到目标,立即返回
if(sum==b)
{
flag=1;
for(i=0;i<f;i++)//输出路径
{
if(i)cout<<' ';
cout<<e[i];
}
}
e[f]=d[ans];//记录路径
for(i=0;i<a;i++)
cout<<e[i]<<' ';
cout<<endl;
dfs(ans+1,f+1,sum+d[ans]);//选
dfs(ans+1,f,sum);//不选,注意不能倒过来,路径会出错
}
int main()
{
cin>>a>>b;
for(c=0;c<a;c++)
cin>>d[c];
sort(d,d+a);
for(i=a-1;i>=0;i--)//计算后面的总和
Sum[i]=Sum[i+1]+d[i];
dfs(0,0,0);
if(!flag)cout<<"No Solution"<<endl;
}