Codeforces Round #503 Div. 2 C - Elections 暴力+贪心

题意:

给定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;
}

猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/81603554