当前位置: 代码迷 >> 综合 >> 贪心-codevs-1098均分纸牌
  详细解决方案

贪心-codevs-1098均分纸牌

热度:6   发布时间:2023-12-20 21:27:37.0

1098 均分纸牌 2002年NOIP全国联赛提高组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
题目描述 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 Description
第一行N(N 堆纸牌,1 <= N <= 100)
第二行A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)

输出描述 Output Description
输出至屏幕。格式为:
所有堆均达到相等时的最少移动次数。‘

样例输入 Sample Input
4
9 8 17 6

样例输出 Sample Output
3

数据范围及提示 Data Size & Hint
e


题解:
题目要求最后每堆的纸牌数都一样多,则可知第一步得求出纸牌的平均数x,而x便是每堆最终要达到的纸牌数。
同时,题中要求移动的次数最少,那么每堆都应该在两次移动以内达到x这个数(左右分别一次)。
这里要用到贪心的方法,对于当前第i堆纸牌,其有num[i]张纸牌,令c=num[i]-x,则我们要将这c张纸牌移动到第i+1堆里去(c为负时,即从第i+1堆中拿纸牌过来),这样便可以保证第i堆在一次操作后就达成x张的条件,同理,第i+1堆向第i+2堆转移,最后转移到第N堆,在这个过程中统计一下移动的次数,就得到答案了。
可能有人会有疑问,如果c<0,且num[i+1]+c<0了怎么办呢,岂不是第i+1堆纸牌数量为负了么?其实大可不必担心这个问题,因为我们的贪心计算过程是没有考虑转移顺序的,第i+1堆虽然暂时为负,但在实际顺序中,这里其实是被后面的纸牌先行填补上来,再分给第i堆的,所以为负只是计算过程中的情况。


//
// main.cpp
// 1098 均分纸牌
//
// Created by 袁子涵 on 15/6/4.
// Copyright (c) 2015年 袁子涵. All rights reserved.
//#include <stdio.h>int main(int argc, const char * argv[]) {int n,poke[105],x=0,ans=0;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&poke[i]);x+=poke[i];}x/=n;for(int i=1;i<n;i++){if(poke[i]==x)continue;poke[i+1]+=poke[i]-x;ans++;}printf("%d\n",ans);return 0;
}