MVP争夺战 [100分]
题目

思路
设MVP得分为 \(scores\) 而 \(t\) 场的总得分为 \(total\),那么可以产生 \(total / scores\) 位MVP。
接着,问题就可以转化为,我们有 \(total / scores\) 位MVP,如何分配每一场的分数才能使每一位MVP的分数刚好为 \(scores\) ?
由此可见,涉及方案问题,考虑使用 \(DFS + 剪枝\) 来解决。
首先,我们对可能的MVP人数进行枚举,在这个过程中,由人数 \(s = total / scores\) 我们可以得知,人数 \(s\) 一定为总得分 \(total\) 的因子,因此对于 \(total \;\%\; s \neq 0\) 的情况便可以进行剪枝。
接着,我们考虑 \(DFS\) 过程中的剪枝。我们将 \(DFS\) 的过程看作要填满 \(n\) 个容量一样的桶,那么首先我们将 \(t\) 个物品降序排列,先考虑体积大的物体,那么我们就可以更快的填满桶,或更快地发现当前方案不可行。
同时,如果当前桶的剩余容量与上一个桶的剩余容量相同时,可以直接跳过当前桶,因为如果当前桶可以放入该物品,那么前一个桶也一定可以,之所以枚举到当前桶一定证明他在前一个桶中已经失败了,而在当前与前一个桶容量相同的桶中也一定会失败。
Code
#include <bits/stdc++.h>
#define int long long
#define pii std::pair<int, int>
#define fir first
#define sec second
#define endl '\n'
#define no std::cout << "NO\n"
#define yes std::cout << "YES\n"
#define all(x) x.begin(), x.end()
const int inf = 1e9;
const int mod = 1e9+7;
bool dfs(std::vector<int>& p, std::vector<int>& mark, int scores, int idx) {
if(idx == p.size()) {
return true;
}
int now = p[idx];
for(int i = 0; i < mark.size(); i ++ ) {
if(i > 0 && mark[i] == mark[i-1]) continue;
if(mark[i] + now <= scores) {
mark[i] += now;
if(dfs(p, mark, scores, idx+1)) {
return true;
}
mark[i] -= now;
}
}
return false;
}
bool check(int n, int scores, std::vector<int>& p) {
std::vector<int> mark(n, 0);
return dfs(p, mark, scores, 0);
}
void solve() {
int t;
std::cin >> t;
std::vector<int> p(t);
for(int i = 0; i < t; i ++ ) {
std::cin >> p[i];
}
int total = accumulate(all(p), 0);
std::sort(all(p), std::greater<int>());
for(int s = t; s >= 1; s -- ) {
if(total % s != 0) continue;
if(total / s < p[0]) continue;
if(check(s, total / s, p)) {
std::cout << total / s << '\n';
return;
}
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int _ = 1;
//std::cin >> _;
while(_--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号