题意:
给定n个选民,m个政党,
然后n行表示每个选民本来所选的政党p和让他选1号政党的花费
问:1号政党赢得选举(票数最多)的最小花费是多少
思路:
首先我们会往贪心方面想,但是因为涉及到当前选择哪个人不一定是最优的,如样例二,可能选另一个就可以代替之前选的两个而获得胜利;
但是我们要是知道1号政党以多少票获得胜利,我们就可以贪心的得到 其最小花费;
其实能想到枚举1号政党赢得胜利的票数k就行,然后贪心的进行选择:
把n个人按c排序,我们从最大的开始选择,
注意,这里选择的是不投给1号政党的人的p值,只要这个值尽量大,那1号政党赢得胜利的花费就最小,
只要在选择的同时保证其他政党的票数<k 并且1号政党的票数>=k;
注意得是那些之前就选择1号政党的必须还得选择1号,所以遇到后跳过,最后用总花费减的时候也要减去这一部分
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int maxn = 3000 + 7;
int n, m;
ll sum = 0, sum2 = 0, ans = 0;
int cnt[maxn];
P a[maxn];
ll solve(int k) {
memset(cnt, 0, sizeof cnt);
ll res = 0, num = 0;
for(int i = n; i > 0; --i) {
if(num + i <= k) break;
if(a[i].second == 1) {
num++; continue;
}
if(cnt[a[i].second]+1 < k) {
res += a[i].first;
cnt[a[i].second]++;
}
else {
num++;
}
}
return res;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
ll p, c; cin >> p >> c;
a[i] = P(c,p);
sum += c;
if(p == 1) sum2 += c;
}
sort(a+1,a+1+n);
int m = n/2+1;
for(int k = 1; k <= m; ++k) {
ans = max(ans, solve(k));
}
printf("%lld\n", sum-sum2-ans);
return 0;
}