题目:
党派竞争投票
有n个人,m个党派,这n个人每个人有一个想要投的党派的编号Pi,如果想要这个人改变他的想法,那么就需要花费Ci元钱。
现在你是编号为1的党派,如果你想要赢(你的票数严格大于其他党派的票数),需要花费的最少的钱是多少。
思路:
将每个人按花费从小到大排序,从0到n枚举获胜需要的票数,遍历所有要投票的人,如果他要投的党派的票数大于当前枚举的票数,就把这个人的票给买过来,最后取所有花费中最小的那个就可以了。
爆int……
代码:
#include <bits/stdc++.h> #include <iostream> using namespace std; const int maxn = 3005; int n,m; struct Voter{ int p; long long c; }v[maxn]; int vis[maxn],hav[maxn]; map<int,int> mp; bool cmp(Voter a,Voter b){ return a.c<b.c; } int main() { scanf("%d%d",&n,&m); for(int i=0; i<n; i++){ scanf("%d%lld",&v[i].p,&v[i].c); mp[v[i].p]++;//统计每个党派最初可以得到的票数 } sort(v,v+n,cmp); long long c=0,ans=1e18; for(int i=0; i<=n; i++){ int num=mp[1]; c = 0; memset(vis,0,sizeof(vis)); memset(hav,0,sizeof(hav)); for(int j=0; j<n; j++){ if(v[j].p==1) {vis[j]=1;continue;} if(mp[v[j].p]-hav[v[j].p]>i){//把这个人的票买过来 c += v[j].c; vis[j] = 1; hav[v[j].p]++; num++; } } for(int j=0; j<n; j++){//如果还是不过枚举的票数就从剩下的人中继续买票(从小到大) if(num>i) break; if(vis[j]) continue; c+=v[j].c; num++; } ans = min(ans,c); } printf("%lld ",ans); return 0; }