题目难度:二星
考察点:贪心、模拟

方法:贪心、模拟

  1. 分析:
    我们分析一下题意,如果想尽可能的让塔的不稳定性小的话,那么就需要让最高塔高度与最低塔高度的差尽可能低,也就是让最高塔的高度尽可能低,最低塔的高度尽可能高。那么我们每次进行操作的时候就是首先将整个高度数组按照从小到大进行排序,然后高度最大值-1,高度最小值+1。一直循环k次, 在每次进行操作的时候分别记录最大值和最小值即可。还需要注意的一点是如果高度最大值-高度最小值<=1的时候,此时就不需要进行操作了,因为此时操作是完全多余的,而题目让我们求的是最少操作次数。
    举个例子:
    就拿样例来说,我们可以进行两次操作:
    第一次操作:我们首先将高度数组排序变为:
    5, 5, 8
    将高度最大值减1,最小值加1,同时记录操作数组的下标(2, 1)此时高度数组变为:
    6, 5, 7
    第二次操作:在将高度数组进行排序,得到:
    5,6,7
    然后将高度最大值减1,最小值加1,同时记录操作数组的下标(2, 3),注意此时的下标并不是排序之后的下标,是原先高度数组的下标,此时高度数组变为:
    6, 6, 6
    进行完两次操作之后,此时不稳定度达到最小,最小为0。然后输出操作数组下标:
    (2, 1)
    (2, 3)

算法实现:
(1). 首先用一个结构体数组保存高度值和下标。
(2). 然后进行k次循环,在每次循环种,首先对结构体数组进行排序,排序规则按照高度值从小到大。排序之后判断高度最大值-高度最小值是否小于等于1,如果小于等于1的话就直接退出此次循环,然后输出结果。否则,将高度最大值-1,高度最小值+1,同时记录此次高度最大值和最小值的下标。
(3). 在执行完k次循环之后,我们在输出高度最大值和最小值的差,此时的差就是不稳定度最小的。然后在根据之前保留的操作数组,输出即可。

  1. 复杂度分析:
    时间复杂度:O(k*nlog(n))
    空间复杂度:O(max(n, k))

  2. 代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e2+5;
    struct Node {
     int x, y;
    }a[MAXN], b[MAXN*10];
    bool cmp(Node A, Node B) {
     return A.x < B.x;
    }
    int main() {
     int n, k; cin>>n>>k;
     for(int i=0; i<n; i++) {
         cin>>a[i].x;
         a[i].y = i+1;
     }
     int cnt = 0;
     while(k--) {
         sort(a, a+n, cmp);
         if(a[n-1].x-a[0].x <= 1) break;
         a[0].x++;
         a[n-1].x--;
         b[cnt].x = a[n-1].y;
         b[cnt++].y = a[0].y;
     }
     sort(a, a+n, cmp);
     cout<<a[n-1].x-a[0].x<<" "<<cnt<<endl;
     for(int i=0; i<cnt; i++) cout<<b[i].x<<" "<<b[i].y<<endl;
     return 0;
    }