给你一些分数,让你每次选2-5个数掉1分,最后使得所有人分数相等。求最后每个人的分数的最大值,并且输出一个方案,不用步骤最少,只要输出每次选哪些人掉分即可。
要思来想去可以摸索到,可以枚举最后的分数R,每次看看可不可行。减掉以后,如果有一个比其他数大很多,那么其他数可能不能和他一起被削掉,所以只好R再小一点,多点数可以消。如果足够的话,可以猜想,假如总分是偶数这样必然有办法可以逐对消光,加入总分是奇数,就是先扣掉三个人的分数,然后逐对地掉分。
这样最坏情况就是到0都不够最大的数掉分,那就随便消了。
但是也有情况可能有一个分数就是0,那么还要考虑一下是不是可以随便来。
反正最后消去的过程是类似的,通过优先队列模拟这个过程就好了。
#define DEBUG(x) cerr<<" DBG::>>"<<#x<<" = "<<(x)<<";"<<endl
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <string.h>
#include <set>
#include <string>
using namespace std;
typedef long long ll;
const int MAXN = 1005;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
struct node {
int i, v;
bool operator<(const node &T) const {
return v < T.v;
}
};
int kase;
int n, r;
int a[MAXN];
int sum, maxi, mini;
priority_queue<node> que;
void outPrint(const vector<node> &args) {
string out;
out.append(n, '0');
for (auto item : args) { out[item.i - 1] = '1'; }
cout << out << endl;
}
void dropItem(const int &num) {
vector<node> tmp(num);
for (auto &item:tmp) {
item = que.top();
que.pop();
item.v = max(0, item.v - 1);
}
outPrint(tmp);
for (auto item:tmp) {
que.emplace(item);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
mini = INF;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
sum += a[i];
maxi = max(maxi, a[i]);
mini = min(mini, a[i]);
que.emplace((node) {i, a[i]});
}
for (r = mini; r > 0; --r) {
if (sum - maxi - r * (n - 1) >= maxi - r) {
break;
}
}
cout << r << endl;
if (r == 0) {
cout << max(sum / 2, maxi) << endl;
} else {
cout << (sum - r * n) / 2 << endl;
}
if ((sum - r * n) % 2 > 0 && n > 2) {
dropItem(3);
}
while (que.top().v > r) {
dropItem(2);
}
return 0;
}
/*
* */
原文:https://www.cnblogs.com/tieway59/p/10923861.html