206003 - 均分纸牌

题解byzzq_helloworld

这是接下来讲题用的文档转化而来的题解,想要学习的可以看过来。

均分纸牌(NOIP 2002 提高组)

虽说是提高组的题目,但真的很简单啊(bushi)

先看题目吧。

纸牌游戏有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)→

纸牌游戏有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)。从 ② 取 1 张牌放到①(10,10,10,10)。

输入格式:

输入第1行为一个整数N(1≤N≤100)。   第2行为N个数,表示每堆纸牌初始数A1,A2,…,An(l≤Ai≤10 000)。

输出格式:

所有堆的牌数均达到相等时的最少移动次数。

算法:

模拟加贪心。

这道题的基础想法为:

  1. 它要求要让每一堆牌的排数一样。-->那我们可以先算出它应有的牌数。
  2. 它每一次都只能移动相邻的牌。 --->每一次我们至少要将一堆牌给移动好。

那就可以写代码了。

参考代码如下:

  for(int i=0; i<n; i++)
	sum+=a[i];
  int num=sum/n;
  for(int i=0; i<n; i++)
	a[i]-=num;
  for(int i=0; i<n-1; i++)
  {
	ans++;
	a[i+1]+=a[i];
  }

结果交上去,听取WA声一片。才二十分!(不是吧,不是吧)

这是为啥呢?--原因很简单,没有处理0。

每次的答案都是n-1,所以要改!

完整参考代码如下:

#include <bits/stdc++.h>
using namespace std;

int main()
{
  int n;
  cin>>n;
  int a[n];
  for(int i=0; i<n; i++)
	cin>>a[i];
  int ans=0;
  int sum=0;
  for(int i=0; i<n; i++)
	sum+=a[i];            // 算出总的牌数
  int num=sum/n;              // 算出平均牌数
  for(int i=0; i<n; i++)
	a[i]-=num;            // 把每一堆牌数减去平均牌数
  for(int i=0; i<n-1; i++)
  {
	  if(a[i]!=0)         // 如果不等于平均的牌数,则移动
	  {
		ans++;
		a[i+1]+=a[i]; // 移动
	  }
  }
  cout<<ans<<endl;
  return 0;
}

请大家根据以上分析,AC掉它。