Codeforces Round #503 (by SIS, Div. 2) C Elections (思维 + 模拟)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/PK__PK/article/details/81707953

题目链接:http://codeforces.com/contest/1020/problem/C

题意:n个人被选举,n个人投票,一开始这n个人都有自己的投票人,但是你可以花钱贿赂这个人,让他改票。你想要1号投票选举胜出。请问最小花费为多少。

题解:题目正常去处理的话 ,正常贪心的很复杂,我们需要考虑,是从比1号少的人中贿赂,还是从比1号多的人去贿赂。思路还是比较复杂的。但是我们可以换个思路,我们可以枚举1号以多少的票数获胜。那么这个贪心的思路就能知道,我们1号需要贿赂多少人。这样我们就不用去纠结他去贿赂谁了。我们只需要去贿赂花费最小的人即可。然后判断那个花费最小即可。大致思路就是这样。其中有点细节需要去理解。

看代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct sss
{
    int id;
    int cost;
}a[3001];
int f[3001];
int g[3001];
int cmp(struct sss x,struct sss y)
{
    return x.cost<y.cost;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].id,&a[i].cost);
        f[a[i].id]++;//计入最开始的投票情况
    }
    long long sum=999999999999,sum2=0,ans;
    sort(a+1,a+n+1,cmp);//按价格排好序
    for(int i=f[1];i<=n;i++)//枚举获胜状态
    {
        sum2=0;
        ans=0;
        for(int j=2;j<=m;j++)
        {
            if(f[j]>=i)
            {
                g[j]=f[j]-i+1;//记录要赢得此选手要在他这买几票
                sum2+=g[j];//记录总共要在比他高的选手这买几票
            }
            else g[j]=0;
        }
        if(i-f[1]<sum2) continue;//如果我在比他高的选手这买的票比我总共买的还多说明情况不存在
        sum2=i-f[1]-sum2;//记录要在比我低的选手这买几票
        for(int j=1;j<=n;j++)
        {
            if(g[a[j].id]!=0)//比我高
            {
                g[a[j].id]--;
                ans+=a[j].cost;
            }
            else{
                if(sum2!=0&&a[j].id!=1)//比我低,并且我还需要买票
                {
                    sum2--;
                    ans+=a[j].cost;
                }
            }
        }
        sum=min(sum,ans);//取最优
    }
    cout<<sum;
}

猜你喜欢

转载自blog.csdn.net/PK__PK/article/details/81707953