均分纸牌
Time Limit:1000MS Memory Limit:65536K
Total Submit:241 Accepted:103
Description
有 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)。
Input
有多个测试案例,每个测试案例
第 1 行输入 N(N 堆纸牌,1 <= N <= 100)
第 2 行输入 A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)
如果输入 N=0, 则表示结束
Output
对每个测试案例,输出一行,内容为使所有堆均达到相等时的最少移动次数。
Sample Input
- 4
- 9 8 17 6
- 0
Sample Output
如果你想到把每堆牌的张数减去平均张数,题目就变成移动正数,加到负数中,使大家都变成 0,那就意味着成功了一半!拿例题来说,平均张数为 10, 原张数 9,8,17,6,变为 - 1,-2,7,-4,其中没有为 0 的数,我们从左边出发:要使第 1 堆的牌数 - 1 变为 0,只须将 - 1 张牌移到它的右边(第 2 堆)-2 中;结果是 - 1 变为 0,-2 变为 - 3,各堆牌张数变为 0,-3,7,-4;同理:要使第 2 堆变为 0,只需将 - 3 移到它的右边(第 3 堆)中去,各堆牌张数变为 0,0,4,-4;要使第 3 堆变为 0,只需将第 3 堆中的 4 移到它的右边(第 4 堆)中去,结果为 0,0,0,0,完成任务。
- 3
- 【分析】
- 其实这个思路我也不知道为什么就是移动的最小的;网上说贪心是一种直觉、、、
- 然而 我又去网上搜了一下。。。。
- http://www.cppblog.com/jince/archive/2010/09/09/126231.aspx
- 这位网友刨根问底的精神值得我去学习orz
- 基于我很烂表达能力 贴一段一本通上的分析
- 其实这个如果都减平均数 还要判断如果减去是0或者移动之后出现了0那么就不用移动了,下面的代码没有减去平均数,直接判断是否等于平均数
- 然后再上面的思路,就不用麻烦看看是否出现0不用移动的特判了。
- 【代码】
- 1#include 2#include 3#include 4 using namespace std;
- 5 int Card[101],
- ave;
- 6 int main() 7 {
- 8 int n,
- step = 0;
- 9 scanf("%d", &n);
- 10
- for (int i = 1; i <= n; i++) 11 {
- 12 scanf("%d", &Card[i]);
- 13 ave += Card[i];
- 14
- }
- 15 ave /= n; //平均值
- 16
- for (int i = 1; i <= n; i++) 17 {
- 18
- if (Card[i] != ave) //不等于平均数就向后一堆借
- 19 {
- 20 Card[i + 1] += Card[i] - ave; //后一堆分给前一堆;后一堆不够先为负,先让当前堆满足平均数。。。
- 21 step++;
- 22
- }
- 23
- }
- 24 printf("%d", step);
- 25
- return 0;
- 26
- }
来源: http://www.bubuko.com/infodetail-2000739.html