货物运输问题,前缀和优化dp,[牛客周赛137 F-小苯的糖果盒]

### 文章目录

  • [@toc](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [一、题目](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [1、题目描述](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [2、输入输出](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [2.1输入](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [2.2输出](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [3、原题链接](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [二、解题报告](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [1、思路分析](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [2、复杂度](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)
  • [3、代码详解](#文章目录 @[toc] 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解)

一、题目

1、题目描述

2、输入输出

2.1输入
2.2输出

3、原题链接

小苯的糖果盒


二、解题报告

1、思路分析

考虑一个经典贪心问题:

两个长度为n的正整数数组a,b,满足 Σa = Σb,允许每次选定i,使得ai 减1,然后让ai + 1 ai - 1 加1,最少需要多少次可以使得 a = b?

答案为: ∑ i = 0 n − 1 ∣ ∑ j = 0 i a j − ∑ j = 0 i b j ∣ \sum_{i=0}^{n-1} |\sum_{j=0}^{i}a_j-\sum_{j=0}^{i}b_j| ∑i=0n−1∣∑j=0iaj−∑j=0ibj∣

即,两个数组的前缀和数组的 差的绝对值 之和,只需证明下界,并且可以取到即可:

先证明下界:

记 s a i = ∑ j = 0 i a i , s b i = ∑ j = 0 i b i sai = \sum_{j=0}^{i}a_i,sbi = \sum_{j=0}^{i}b_i sai=∑j=0iai,sbi=∑j=0ibi

那么对于下标 i:

  • 如果 sai > sbi,说明 0...i 的数至少需要向i+1...n运输 sai - sbi
  • 否则,说明 i+1...n 的数至少需要向 0...i 运输 sbi - sai

因此,答案的下界是 ∑ i = 0 n − 1 ∣ s a i − s b i ∣ \sum_{i=0}^{n-1} |sai - sbi| ∑i=0n−1∣sai−sbi

在证明可以构造方案使得下界取到:

从小到大枚举 i

  • i = 0
    • 如果 sa0 > sb0,那么让 a0 向 a1 运输 a0 - b0
    • 否则,让a1 向 a0 运输 b0 - a0(对于a1不够的情况我们允许出现负数,这不会影响i = 1的情况判定,这和洛谷 均分纸牌那题的原理是一样的)
  • i = 1......

如此构造下去,我们一定可以构造出一个合法方案

对于本题,因为 sum a 最大不过 10000,所以平方数最多可取 0 x 0,1 x 1,......100 x 100,共101 个数

我们考虑 定义 dpi, j, k 为 ai = j * j, ∑ j = 0 i a j = k \sum_{j=0}^{i}a_j = k ∑j=0iaj=k ,且 a0...i 单调不减的最小代价

我们转移的时候枚举ai = j * j,以及 ∑ j = 0 i a j = k \sum_{j=0}^{i}a_j = k ∑j=0iaj=k,那么 dpi, j, k = min dpi - 1, x, k - j \* j,我们预处理一下前缀min即可

可以滚动数组优化(见代码)

2、复杂度

时间复杂度: O(100nΣa ) 空间复杂度:O(100Σa)

3、代码详解

c++ 复制代码
#include <bits/stdc++.h>
namespace ranges = std::ranges;
using i64 = long long;

constexpr int inf = 1E9;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    std::cin >> t;
    while (t--) {
        int n;
        std::cin >> n;
        std::vector<int> a(n);
        int M = 0;
        for (int i = 0; i < n; ++i) {
            std::cin >> a[i];
            M += a[i];
        }
        std::vector dp(101, std::vector<int>(M + 1, inf)), min(101, std::vector<int>(M + 1, inf));
        for (int i = 0; i <= 100; ++i) {
            min[i][0] = 0;
        }
        int s = 0;
        for (int x : a) {
            s += x;
            for (int i = 0; i <= 100; ++i) {
                for (int j = i * i; j <= M; ++j) {
                    dp[i][j] = min[i][j - i * i] + std::abs(j - s);
                }
            }
            for (int j = 0; j <= M; ++j) {
                min[0][j] = dp[0][j];
                for (int i = 1; i <= 100; ++i) {
                    min[i][j] = std::min(min[i - 1][j], dp[i][j]);
                }
            }
        }

        int ans = inf;
        for (int i = 0; i < 101; ++i) {
            ans = std::min(ans, dp[i][M]);
        }
        if (ans == inf) {
            ans = -1;
        }
        std::cout << ans << '\n';
    }
    
    return 0;
}
相关推荐
漂流瓶jz27 分钟前
UVA-1442 洞穴 题解答案代码 算法竞赛入门经典第二版
c++·算法·题解·aoapc·算法竞赛入门经典·uva
叠层归一研究院2 小时前
基于极限自指的叠层归一宇宙结构理论——无元外部封闭系统的内生区分模型
人工智能·经验分享·算法·agi
Selvaggia3 小时前
Diffusion Model 的基本原理与模型架构
算法
wabs6664 小时前
关于二叉树【力扣572.另一棵树的子树的思考】
数据结构·c++·算法·leetcode·二叉树
hanlin034 小时前
刷题笔记:力扣第41题-缺失的第一个正数
笔记·算法·leetcode
shehuiyuelaiyuehao5 小时前
算法50,分治归并,数组中的逆序对
java·算法
阳明山水5 小时前
校准分位数驱动智能库存决策
人工智能·深度学习·算法·机器学习·架构
别动我齐刘海6 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
zhangfeng11337 小时前
《从“人工适配“到“智能生成“:KernelSwift 跨国产芯片算子迁移全栈方案解读》 —— 强调范式跃迁和跨硬件属性,适合偏架构分析的写法
人工智能·算法·华为·ai编程·npu
0+1117 小时前
算法 --滑动窗口
c++·算法·leetcode