天梯赛练习题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;
}
posted @ 2023-03-08 21:37  Vijurria  阅读(62)  评论(0编辑  收藏  举报