使用01背包dp思路解决。

目的是找出是否能有一个结果总价值为k,暴力枚举复杂度太大。

不妨将问题转变为 总价值为k是否可以被凑出来

建立一个dp数组,范围0到k+1,初始化false,dp[i]表示价值i是否可以被凑出来。

dp[0] 置 true,当我们什么物品都不选,价值为0。

从前向后遍历:

j是目标价值,p是当前物品价值,j-p表示"如果我们选择当前物品,还需要凑出多少价值"。

对于每一个物品,如果我们能用之前的物品凑出 j-p,那么再加上当前的物品(价值 p),就能凑出 j:

dp[i] 表示能否拼凑出价值i。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n,k;
    cin>>n>>k;
    vector<int> v(n+1);
    vector<bool> dp(k+1,false);
    dp[0]=true;
    for(int i=1;i<=n;++i) cin>>v[i];
    for(int i=1;i<=n;++i){
        int p = v[i];
        for(int j=k;j>=p;j--){
            if(dp[j-p]) dp[j]=true;
        }
    }
    cout<<(dp[k]?"Yes":"No");
}