枚举+贪心--经常用到的思路--过程不好弄是--枚举结果C. Elections

http://codeforces.com/contest/1020/problem/C

题意:有n个人投票,m个政党,接下来n行,每i行两个数pi,ci,表示i这个人投票给pi,想让他投票给1号政党需要花费ci元。问要是一号政党胜出,至少需要花多少money。

分析:做题的时候一直想贪心,但是情况好多,好复杂,最后就gg了。

一看官方题解恍然大悟,这是同一个经常用到的思路,反正以前见到过,很好啊。

枚举一号政党得到i票所需要的花费,在选择的时候用到了很简单的贪心,就是选择花费少的呗。

长了一个姿势,就是vector开的数组也可以排序,以前没用过,也没见到过。

#include <bits/stdc++.h>
#define sz(x) ((int)x.size())
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;
typedef long double ld;
int n,m;
bool chk[3010];
vector<pair<int,int> > a, b[3010];
int main() {
	scanf("%d%d",&n,&m);
	int init = 0;
	for(int i=1; i<=n; i++) {
		int p,c;
		scanf("%d%d", &p, &c);
		if(p == 1) {
			init++;//一号政党得到的票数
			continue;
		}
		b[p].push_back(make_pair(c,i));//先按a由小到大排序,a相同按b由小道德排序。统计p得到的票数
		a.push_back(make_pair(c,i));//想让i好投一号政党的花费
	}
	sort(all(a));
	for(int i=1; i<=m; i++) sort(all(b[i]));
	ll res = 9e18;
	for(int i=max(init,1); i<=n; i++) {//枚举一号政党得到的选票数
		memset(chk, 0, sizeof(chk));
		int cnt = 0; ll cost = 0;
		for(int j=1; j<=m; j++) {
			if(sz(b[j]) >= i) {
				for(int k=0; k<sz(b[j])-i+1; k++) {
					cost += b[j][k].first;
					chk[b[j][k].second] = 1;
					cnt++;
				}
			}
		}
		//cout<<"dbg1"<<endl;
		if(cnt > i) continue;
		for(int j=0; j<sz(a) && cnt+init < i; j++)
			if(!chk[a[j].second]) {
				cost += a[j].first;
				cnt++;
			}
		res = min(res, cost);
	}
	printf("%lld", res);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37891604/article/details/81625843