CodeForces - 1020C C - Elections(贪心+枚举)

题目:

党派竞争投票

有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\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/sykline/p/10455293.html