均分纸牌----贪心

题目描述

有N堆纸牌,编号分别为1,2,…,N。每堆上有若干张,但纸牌总数必为N的倍数。可以在任一堆上取若干张纸牌,然后移动。
移牌规则为:在编号为1堆上取的纸牌,只能移到编号为2的堆上;在编号为N的堆上取的纸牌,只能移到编号为N-1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
例如N=4,4堆纸牌数分别为:①9②8③17④6移动3次可达到目的:
从③取4张牌放到④(981310)->从③取3张牌放到②(9111010)>从②取1张牌放到①(10101010)。

输入

N(N堆纸牌,1<=N<=100)
A1A2…An(N堆纸牌,每堆纸牌初始数,I<=Ai<=10000)

输出

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

样例输入
4
9 8 17 6

样例输出
3

题解

求出平均数,用每个数字减去平均数,得到的数字有正有负,再从左往右将数字移动,不论正负
例如9 8 17 6,平均数为10
减去平均数得到-1  -2  7  -4
第一次0  -3  7  -4
第二次0  0  4  -4
第三次0  0  0  0
这样就得到了答案
不过有一点需要注意过滤掉首尾的0,不过中间的0不能过滤,但是不会增加移动的步数

-2      2      0       0       -2       2

只移动了2次
 
附上代码

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
 int n,i,s[300],sum,ave,j,count,k;
 while(cin>>n)
 {
  memset(s,0,sizeof(s));
  sum=0;
  for(i=1;i<=n;i++)
  {
   cin>>s[i];
   sum+=s[i];
  } 
  ave=sum/n;
  for(i=1;i<=n;i++) s[i]-=ave;
  i=1,j=n;
  while(s[i]==0&&i<n) i++;//记得写i,j的范围 
  while(s[j]==0&&j>1) j--;
  count=0;
  while(i<j)//不能是for(k=i;k<j;k++) 
  {
   if(s[i]!=0)//防止-2 2 0 0 2 2 的情况 
   {
    s[i+1]+=s[i];
    count++;
   }
   i++;
  }
  cout<<count<<endl;
 }
 return 0;
}
发布了37 篇原创文章 · 获赞 3 · 访问量 1173

猜你喜欢

转载自blog.csdn.net/qq_45721778/article/details/104907349
今日推荐