1 条题解

  • 0
    @ 2026-1-27 21:29:53
    #include <bits/stdc++.h>
    using namespace std;
    
    // [1] m-目标和;n-输入的正整数个数
    int m,n;
    // [2] arr数组-存储输入的N个正整数(下标1~n)
    int arr[2100];
    // [3] dp数组-动态规划状态,dp[j]表示子集和为j的方案数,用long long防止方案数过大溢出int
    long long dp[11000]={};
    
    int main() {
        // 问题分析:01背包计数问题,每个元素只能选一次,求子集和为M的方案数(相同值不同位置算不同方案)
        // 解题步骤:1.初始化dp[0]=1(空集是和为0的唯一方案);2.逆序遍历每个元素,更新dp[j] += dp[j-arr[i]](选当前元素的方案数=前j-arr[i]的方案数);
        //          3.最终dp[m]即为和为M的方案数
        
        cin>>n>>m;  // [4] 读取元素个数n和目标和m
        for(int i=1;i<=n;i++) cin>>arr[i];  // [5] 读取N个正整数,存入arr数组
        
        dp[0]=1;  // [6] 初始化:和为0的方案数为1(选择空集)
        
        // 01背包核心循环:遍历每个元素,逆序更新方案数
        for(int i=1;i<=n;i++){  // [7] 外层循环:遍历每个元素(每个元素仅能选一次)
            // 内层循环:逆序遍历目标和(避免重复选择同一元素,保证每个元素仅被计算一次)
            for(int j=m;j>=arr[i];j--){
                // [8] 状态转移:不选当前元素时dp[j]不变;选当前元素时,方案数增加dp[j-arr[i]](前j-arr[i]的方案数)
                dp[j] = dp[j] + dp[j-arr[i]];
            } 	
        }
        cout<<dp[m];  // [9] 输出子集和为m的方案数
        return 0;
    }
    
    • 1

    信息

    ID
    1355
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者