本人已参与[新人创作礼] 活动,一起开启掘金创作之路 [问题描述] 有 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)。 其实就是贪心:
````js`
`#include<stdio.h>
#include<string.h>
int main()
{
int ncase,i,n;
scanf("%d",&ncase);
while(ncase--)
{
int arr[1000],sum=0,v,num=0;
memset(arr,0,sizeof(arr));
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&arr[i]);
sum+=arr[i];
}
v=sum/n;
for(i=0;i<n-1;i++)
{
if(arr[i]<v){arr[i+1]=arr[i+1]-v+arr[i];num++;}
if(arr[i]>v){arr[i+1]=arr[i+1]+v-arr[i];num++;}
}
printf("%d\n",num);
}
return 0;
}
#include<stdio.h>
#include<string.h>
int temp;
void move(int i,int v,int s[100],int d[100])
{
if(i<0||d[i]==0) //i<0,不用解释了,d[i]==0代表前i堆都分配好了
return;
if(d[i]==1) //从后一堆拿
{
printf("从第%d堆纸牌向%d堆纸牌移动%d张!\n",i+1,i,v-s[i]);
move(i-1,v,s,d); //递归
d[i]=0; //置零,其实一次递归就可以让前i堆都分配成功!
}
else if(d[i]==2) //给后一堆
{
printf("从第%d堆纸牌向%d堆纸牌移动%d张!\n",i,i+1,s[i]-v);
d[i]=0;
}
}`
//处理当前i堆函数。。。其实我自己也不知道怎么定义这个函数才对
/*
参数说明:
i:当前堆
v:平均值
s:堆状态序列值
d:记录分配情况:1代表向后一堆取,2代表向后一堆给,0代表本堆已经是平均值了,没有操作
n:堆数
*/
void mypow(int i,int v,int s[100],int d[100],int n)
{
if(i==n) //前n-1堆分配成功后,第n堆一定是平均值,所以直接返回
return;
if(s[i]<v) //如果本堆小于平均值,就向前一堆去要
{
d[i]=1;
if(s[i+1]-(v-s[i])>=0) //如果前一堆可以给,就直接移动,事实上这次给可以让前i堆纸牌值全部为平均值
{
temp=1;
move(i,v,s,d); //移动函数
}
s[i+1]=s[i+1]-(v-s[i]); //第i+1堆状态变化
mypow(i+1,v,s,d,n); //递归求解i+1堆
}
else if(s[i]>v) //如果本堆大于平均值,就给后一堆
{
s[i+1]=s[i+1]+(s[i]-v);
d[i]=2;
temp=1;
move(i,v,s,d); //这里的move其实可以直接写成printf
mypow(i+1,v,s,d,n); //递归求解i+1堆
}
else if(s[i]==v) //如果本堆等于平均值,当然不用移动了
{
d[i]=0;
mypow(i+1,v,s,d,n); //递归求解i+1堆
}
return;
}
int main()
{
int n,sum,v;
int s[100],d[100];
int i;
int count;
while(scanf("%d",&n)!=EOF&&n!=0)
{
memset(d,0,sizeof(d));
sum=0;
v=0;
count=0;
for(i=1;i<=n;i++)
{
scanf("%d",&s[i]);
sum=sum+s[i];
}
v=sum/n;
temp=0;
mypow(1,v,s,d,n);
if(!temp) //这个就是不用分配标记
printf("不用移动了!\n");
}
return 0;
}