如何用最少的金额贿赂选民以赢得选举

这是一道很皮的编程题

题目来源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;
}

猜你喜欢

转载自blog.csdn.net/m0_37772174/article/details/81605979