本题乍一看像完全背包问题,但是仔细分析可以看出其实是一道bfs。bfs的状态即为当前买的糖数,从0搜索到m。要注意的是超过m的状态需要剪枝,否则容易越界。
时间复杂度为
空间复杂度为
以下是AC代码:

#define maxm 10005
class Solution {
public:
    /**
     * 返回最少需要买的糖包数
     * @param n int整型 表示共有多少种糖包
     * @param m int整型 表示一共需要买的糖数
     * @param num int整型一维数组 表示每种糖包所含的糖的数量
     * @param numLen int num数组长度
     * @return int整型
     */
    int solve(int n, int m, int* num, int numLen) {
    int dis[maxm];
    memset(dis,0,sizeof(dis));//初始设置为0,既用来标记,也用来保存答案
    queue<int> q;
    q.push(0);//初始状态为0
    while(!q.empty())
    {
        int t=q.front();
        if(t==m)
            break;
        q.pop();
        for(int i=0;i<n;i++)
        {
            int w=num[i]+t;
            if(w<=m&&!dis[w])//w超过m不予考虑,dis[w]为0表示没有访问过该状态
            {
                dis[w]=dis[t]+1;
                q.push(w);
            }
        }
    }
    return dis[m];
    }
};

另外,暴力也可以做本题,但是本质上和bfs的做法是相同的,并且代码量和bfs相当。
时间复杂度为
空间复杂度为

#define maxm 10005
class Solution {
public:
    /**
     * 返回最少需要买的糖包数
     * @param n int整型 表示共有多少种糖包
     * @param m int整型 表示一共需要买的糖数
     * @param num int整型一维数组 表示每种糖包所含的糖的数量
     * @param numLen int num数组长度
     * @return int整型
     */
    int solve(int n, int m, int* num, int numLen) {
    int book[maxm];
    memset(book,0,sizeof(book));
    int ans=0;
    vector<int> vec[maxm];
    vec[0].push_back(0);
    while(!book[m])
    {
        for(int i=0;i<vec[ans].size();i++)
        {
            int u=vec[ans][i];
            for(int j=0;j<n;j++)
            {
                if(u+num[j]<=m&&book[u+num[j]]==0)
                {
                    book[u+num[j]]=1;
                    vec[ans+1].push_back(u+num[j]);
                }
            }
        }
        ans++;
    }
    return ans;
    }
};