csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:均分纸牌

csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:均分纸牌

题目描述

有 N N N 堆纸牌,编号分别为 1 , 2 , ... , N 1,2,\ldots,N 1,2,...,N。每堆上有若干张,但纸牌总数必为 N N N 的倍数。可以在任一堆上取若干张纸牌,然后移动。

移牌规则为:在编号为 1 1 1 堆上取的纸牌,只能移到编号为 2 2 2 的堆上;在编号为 N N N 的堆上取的纸牌,只能移到编号为 N − 1 N-1 N−1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。

现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

例如 N = 4 N=4 N=4 时, 4 4 4 堆纸牌数分别为 9 , 8 , 17 , 6 9,8,17,6 9,8,17,6。

移动 3 3 3 次可达到目的:

  • 从第三堆取 4 4 4 张牌放到第四堆,此时每堆纸牌数分别为 9 , 8 , 13 , 10 9,8,13,10 9,8,13,10。
  • 从第三堆取 3 3 3 张牌放到第二堆,此时每堆纸牌数分别为 9 , 11 , 10 , 10 9,11,10,10 9,11,10,10。
  • 从第二堆取 1 1 1 张牌放到第一堆,此时每堆纸牌数分别为 10 , 10 , 10 , 10 10,10,10,10 10,10,10,10。
输入格式

第一行共一个整数 N N N,表示纸牌堆数。

第二行共 N N N 个整数 A 1 , A 2 , ... , A N A_1,A_2,\ldots,A_N A1,A2,...,AN,表示每堆纸牌初始时的纸牌数。

输出格式

共一行,即所有堆均达到相等时的最少移动次数。

输入输出样例 1
输入 1
复制代码
4
9 8 17 6
输出 1
复制代码
3
说明/提示

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 100 1 \le N \le 100 1≤N≤100, 1 ≤ A i ≤ 10000 1 \le A_i \le 10000 1≤Ai≤10000。

分析思路

本题要求通过最少的相邻移动次数,使所有堆的纸牌数相等。

已知纸牌总数是堆数 N 的倍数,因此平均值 avg = 总牌数 / N

贪心策略:从左到右依次处理每一堆。

  • 若当前堆的纸牌数不等于 avg,则必须通过一次移动(与右边相邻堆交换)来调整。
  • 具体地,计算当前堆与平均值的差值 d = a[i] - avg,然后将这个差值移动到下一堆(即 a[i+1] += d),同时移动次数加 1。
  • 这样处理后,当前堆就变成了 avg,而差值的影响传递给了下一堆。
  • 继续处理下一堆,直到最后一堆(最后一堆必然已是 avg,无需再移动)。

正确性

每次移动只涉及相邻两堆,且保证已处理过的左边部分全部达到平均值,不会因为后续调整而破坏。这种局部最优策略最终得到全局最优解,移动次数即为需要调整的堆数(即 a[i] != avg 的堆数,但不包括最后一堆)。

时间复杂度 O(N),空间复杂度 O(N)


代码实现

cpp 复制代码
#include <bits/stdc++.h>  
using namespace std;

int n;  // 堆数
int a[105]; // 每堆纸牌数,最大 N=100,开稍大一点
int s, avg, ans; // s:总和, avg:平均值, ans:最少移动次数

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        s += a[i]; // 累加总张数
    }
    avg = s / n; // 计算平均值(题目保证整除)

    for (int i = 1; i < n; ++i) {   // 只处理到第 n-1 堆
        if (a[i] != avg) {
            // 当前堆与平均值的差值,移动到下一堆
            int d = a[i] - avg;
            a[i+1] += d;
            ans++; // 发生一次移动
        }
    }
    cout << ans << endl;
    return 0;
}

功能分析

输入
  • 第一行:整数 N(1 ≤ N ≤ 100)
  • 第二行:N 个整数,表示每堆初始纸牌数(1 ≤ Ai ≤ 10000)
处理
  1. 计算总和 s 和平均值 avg
  2. 从左到右扫描前 N-1 堆:
    • 若当前堆不等于平均值,则将其与平均值的差值(可正可负)加到下一堆,并计数一次。
  3. 输出计数结果。
输出

一个整数,即最少移动次数。

样例验证

输入:

复制代码
4
9 8 17 6
  • 总和 = 40,avg = 10
  • i=1: a[1]=9 ≠10 → d=-1 → a[2]=8+(-1)=7, ans=1
  • i=2: a[2]=7 ≠10 → d=-3 → a[3]=17+(-3)=14, ans=2
  • i=3: a[3]=14 ≠10 → d=4 → a[4]=6+4=10, ans=3
  • 输出 3,与题目示例一致。

各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

【秘籍汇总】(完整csp信奥赛C++学习资料):

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

4、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
EQUINOX12 小时前
2026年码蹄杯 本科院校赛道&青少年挑战赛道提高组初赛(省赛)第一场,个人题解
算法
萝卜小白2 小时前
算法实习Day04-MinerU2.5-pro
人工智能·算法·机器学习
Liangwei Lin2 小时前
洛谷 P3133 [USACO16JAN] Radio Contact G
数据结构·算法
weixin_513449962 小时前
PCA、SVD 、 ICP 、kd-tree算法的简单整理总结
c++·人工智能·学习·算法·机器人
code_pgf2 小时前
Qwen2.5-VL 算法解析
人工智能·深度学习·算法·transformer
烟锁池塘柳02 小时前
一文讲透 C++ / Java 中方法重载(Overload)与方法重写(Override)在调用时机等方面的区别
java·c++·面向对象
Code-keys3 小时前
Android Codec2 Filter 算法模块开发指南
android·算法·音视频·视频编解码
无忧智库3 小时前
低空经济新基建:构建低空飞行大数据中心与行业应用算法工厂的全景式蓝图(WORD)
算法
yolo_guo3 小时前
glog单行 30000 字节限制问题
c++