天梯赛练习题L3-001 凑零钱(dfs 爆搜)
https://pintia.cn/problem-sets/994805046380707840/exam/problems/994805054207279104
题目大意:
给定n个硬币,总共需要我们凑出m块钱。
问我们能凑出的硬币的最小字典序是什么?
可以的话输出最小的字典序数列,不可以的话输出 “No Solution”。
输入样例 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
我一开始感觉dp可以做,想半天只知道怎么凑数,不大知道怎么计算位置和实际的数量(改天再来想想dp能不能做
暴力做法:
这题对时间卡得有点狠,注意剪枝(我们只要一开始按从小到大的顺序排一下序,这样在进行深搜的时候,就可以保证一定是按照最小字典序的顺序在进行了,所以一旦出现答案,那这就是我们想要的那个
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18,MINN=-1e18;
const LL N=1e6+10,M=2023;
const LL mod=998244353;
const double PI=3.1415926535;
#define endl '\n'
LL n,m,a[N];
vector<LL> ans;
bool flag=false;
void dfs(LL idx,LL res)
{
if(flag==true) return ;
if(res==m)
{
flag=true;
for(int i=0;i<ans.size();i++)
{
cout<<ans[i];
if(i!=ans.size()-1) cout<<" ";
}
cout<<endl;
return ;
}
if(idx>n||res>m) return ;
if(res+a[idx]<=m)
{
ans.push_back(a[idx]);
dfs(idx+1,res+a[idx]);
ans.pop_back();
}
dfs(idx+1,res);
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
//cin>>T;
while(T--)
{
cin>>n>>m;
LL sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
if(sum<m) cout<<"No Solution"<<endl;
else if(sum==m)
{
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
cout<<a[i];
if(i!=n) cout<<" ";
}
cout<<endl;
}
else
{
sort(a+1,a+1+n);
dfs(1,0);//从第一个数字开始,总和为0
if(flag!=true) cout<<"No Solution"<<endl;
}
}
return 0;
}