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: a1=9 ≠10 → d=-1 → a2=8+(-1)=7, ans=1
  • i=2: a2=7 ≠10 → d=-3 → a3=17+(-3)=14, ans=2
  • i=3: a3=14 ≠10 → d=4 → a4=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;
}
相关推荐
写代码写到手抽筋6 小时前
5G上行DCI字段判定:端口 流数 PMI选择详解
java·算法·5g
xieliyu.6 小时前
Java算法精讲:双指针(二)
java·开发语言·算法
苏宸啊6 小时前
IPC管道
linux·c++
BestOrNothing_20157 小时前
ROS2 话题通信实战:消息对象、Publisher 发布器与 Subscriber 订阅器保姆级教程
c++·ros2·subscriber·publisher·话题通信
wayz117 小时前
Momentum:PSL(心理线指标)技术指标详解
算法·金融·数据分析·量化交易·特征工程
8Qi88 小时前
LeetCode 213:打家劫舍 II(House Robber II)—— 题解 ✅
算法·leetcode·职场和发展·动态规划
三品吉他手会点灯8 小时前
C语言学习笔记 - 44.运算符和表达式 - 运算符2 - 除法与取余运算符
c语言·开发语言·笔记·算法
乐迪信息8 小时前
乐迪信息:AI算法盒子实时识别船舶烟雾与火焰异常
大数据·人工智能·算法·安全·目标跟踪
J-Tony118 小时前
【JVM】根可达算法
jvm·算法
艾iYYY8 小时前
string 类的模拟实现
android·服务器·c语言·c++·算法