这是一道很皮的编程题
题目来源codeforces
原则:尽可能不贿赂需要金额较高的选民,保证敌对阵营的选民人数均小于一定值
这次直接上代码
//作者:cclplus 有需请联系[email protected]
#include <iostream>
#include <algorithm>
#include <vector>
#include <memory.h>
using namespace std;
const int nmax = 3000 + 5;
const long long max_ll = 9223372036854775807;
int peo_num[nmax];//选择第i个政党所持有的选民总人数
bool bribe[nmax];//是否向i行贿
struct ccl {
long long vote;//投票意向
long long cost;//收买花费
};
bool comp(ccl a, ccl b) {
return a.cost < b.cost;
}
int main() {
ios::sync_with_stdio(false);
long long n, m, i, j, temp1;
long long temp2,ans, sum_ll;
cin >> n >> m;
vector<ccl> wiseman(n+1);
for (i = 1; i <= n; i++) {
cin >> temp1 >> temp2;
wiseman[i].vote = temp1;
wiseman[i].cost = temp2;
}
//结构体排序
sort(wiseman.begin(),wiseman.end(),comp);
temp1 = (n + 1) / 2;
ans = max_ll;
for (i = 0; i <=temp1; i++) {//设定其他政党所允许的最大人数
sum_ll = 0;
memset(peo_num, 0, sizeof(peo_num));
memset(bribe, false, sizeof(bribe));
for (j = n; j >= 1; j--) {
//当该选民所投的政党人数小于i,或者该选民所投政党为政党1,不需要改变他的意向
//尽可能不去改变贿赂需要较高代价的对象
if ((peo_num[wiseman[j].vote] <i) || (wiseman[j].vote == 1)) {
peo_num[wiseman[j].vote]++;
}
else {
sum_ll+= wiseman[j].cost;
peo_num[1]++;
bribe[j] = true;//选民j已被贿赂
}
}
for (j = 1; j <= n; j++) {
if ((peo_num[1] <= i )&&( wiseman[j].vote != 1 )&& (!bribe[j])) {
sum_ll += wiseman[j].cost;
peo_num[1]++;
bribe[j] = true;
}
}
if (peo_num[1]>i)ans = min(sum_ll, ans);
}
cout << ans << endl;
return 0;
}