题目描述
有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;
}