最少的元素个数使和为 target

思路

这是 0/1 背包的变种。

设 dp[j] 表示凑出和 j 所需的最少元素个数。

  • 初始化 dp[0] = 0,其他为无穷大。

  • 对每个数 x,从后往前更新:

    dp[j] = min(dp[j], dp[j - x] + 1)

但 target 可能为负,且数组元素可能为负,因此不能直接用下标表示负数。

若 target 绝对值不大,可以加偏移量 OFFSET。

若 target 绝对值过大,则伪多项式算法不可行,应说明使用 meet-in-the-middle 或搜索剪枝。

这里给出偏移量版本。

代码

c

复制代码
#include <stdio.h>
#include <string.h>
#include <limits.h>

#define MAXN 1005
#define MAXT 200005
#define INF 0x3f3f3f3f

int min(int a, int b) {
    return a < b ? a : b;
}

int main() {
    int n, target;
    int nums[MAXN];
    int dp[MAXT];
    int offset = 100000;

    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &nums[i]);
    scanf("%d", &target);

    int size = 200005;
    for (int i = 0; i < size; i++) dp[i] = INF;
    dp[offset] = 0;

    for (int i = 0; i < n; i++) {
        int x = nums[i];
        if (x >= 0) {
            for (int j = size - 1; j >= x; j--) {
                if (dp[j - x] != INF)
                    dp[j] = min(dp[j], dp[j - x] + 1);
            }
        } else {
            for (int j = 0; j < size + x; j++) {
                if (dp[j - x] != INF)
                    dp[j] = min(dp[j], dp[j - x] + 1);
            }
        }
    }

    int idx = target + offset;
    if (idx < 0 || idx >= size || dp[idx] == INF)
        printf("-1\n");
    else
        printf("%d\n", dp[idx]);

    return 0;
}
相关推荐
炽橙超真云1 小时前
2D 工程图纸如何自动转成可编辑 3D 模型?拆解读图与建体两条技术路径(DXF/DWG/PDF 到 STEP)
算法·3d·工业智能·工业ai
Zip-List1 小时前
工作小记-pytorch的算子优化: 转gpu核函数 python调c
c语言·c++·pytorch·python·cuda
夕除1 小时前
redis--dict rehash
算法·哈希算法
暖焰核心1 小时前
多态全解——虚函数、重写、虚表与多态原理
c++
云上先途11 小时前
Agent 轨迹数据一般包含哪些内容,加工的核心目标是什么?
人工智能·算法·机器学习
白杨尚青2 小时前
C++入门篇(十八):模板进阶——非类型参数、特化全家桶与分离编译(收官篇)
开发语言·c++·笔记·模板·偏特化·分离编译
佳木逢钺2 小时前
从火灾模拟到系统热寂:一个双非运维如何用零 GPU 推导出多智能体系统的终极死锁
人工智能·python·算法·多智能体
垆边人似月.2 小时前
网格最小代价路径,总代价不超过 budget
算法
虚无的纽扣2 小时前
【力扣刷题】第五天:将 x 减到 0 的最小操作数、最大连续1的个数 III
算法·leetcode·职场和发展