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