【题解】均分纸牌
作者:互联网
题目描述
有N堆纸牌,编号分别为1,2,...,N。每堆上有若干张,但纸牌总数必为N的倍数。可以在任一堆上取若干张纸牌,然后移动。
移牌规则为:在编号为1堆上取的纸牌,只能移到编号为2的堆上;在编号为N的堆上取的纸牌,只能移到编号为N-1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数一样多。
例如N=4,4堆纸牌数分别为:
① 9 ② 8 ③ 17 ④ 6
移动3次可达到目的:
从③取4张牌放到④(9 8 13 10)→从③取3张牌放到②(9 11 10 10)→从②取1张牌放到①(10 10 10 10)。
输入格式
第一行为一个整数N,表示N堆纸牌(1≤N≤100);
第二行为N个整数,表示每堆纸牌初始数Ai(1≤Ai≤10000)。
输出格式
所有堆均达到相等时的最少移动次数。
输入样例
4
9 8 17 6
输出样例
3
题解
容易发现,纸牌数一样多实际上就相当于是每一位都变成纸牌数总和的平均数。
把每一位的数量都减去平均数,就是这一位需要移动的纸牌。
显然所有位加起来后就为0,那么可以从左加到右,这样肯定是最优情况(这里把负数情况也看做移动)。(原因:每一位最多只用移动一次)
#include <iostream> #include <cmath> #define MAXN 102 using namespace std; int n; int a[MAXN]; int l, r; int sum; int ans; int main() { cin >> n; for(register int i = 1; i <= n; i++) { cin >> a[i]; sum += a[i]; } sum /= n;//求平均值 for(register int i = 1; i <= n; i++) { a[i] -= sum; } l = 1; r = n; while(!a[l]) l++; //去除无用0 while(!a[r]) r--; //同上 while(l < r)// 把问题转换为 给正数纸牌 加上负数纸牌 最后必然变为0 { a[l + 1] += a[l]; a[l] -= a[l]; ans++; while(!a[l]) l++;// 同上 } cout << ans; return 0; return 0; }参考程序
标签:10,纸牌,int,题解,编号,均分,每堆,移动 来源: https://www.cnblogs.com/kcn999/p/10800514.html