不充钱,你怎么AC?
题目:
显然就是使每堆牌达到总体的平均数,尽量使每次移动时的牌数最大,这就类似于飞行棋,将几个棋子叠起来一起走是最优的。
我们将数组变为关于平均数的浮动,然后每次寻找距离最小的一正一负的两个位置,将绝对值小的补上,也就是将其中一个变为0(若绝对值相等就是两个),再从多的往少的一个个标记,代表会往那边移动一次。注意这里要开一个左一个右,因为向左和向右是代表的两种不同得方案。那么这样我们就达到了每次移动牌数尽可能最多。可能思路讲的不是很清晰,具体请参考代码。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #define N 110 8 using namespace std; 9 10 struct data11 {12 int l,r;13 }14 f[N];15 int a[N];16 int main()17 {18 int i,n,k,sum,l,r;19 scanf("%d",&n);20 sum=0;21 for (i=1;i<=n;i++)22 {23 scanf("%d",&a[i]);24 sum+=a[i];25 f[i].l=f[i].r=0;26 }27 sum/=n;28 for (i=1;i<=n;i++) a[i]-=sum;29 l=r=1;30 while (1)31 {32 while (a[l]>=0&&l<=n) l++;33 while (a[r]<=0&&r<=n) r++;34 if (r>n||l>n) break;35 k=min(-a[l],a[r]);36 a[l]+=k;37 a[r]-=k;38 if (r>l) for (i=r;i>l;i--) f[i].l=1;39 else for (i=r;i