Elections (枚举)

本文解析了CodeForces 1020C题目的算法解决方案,通过枚举1号队伍获胜所需的票数,确定使1号队伍获胜所需的最小花费。算法考虑了每个人对队伍的支持成本,以及如何通过购买选票来优化总成本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目http://codeforces.com/problemset/problem/1020/C

n个人,m支队伍,
每个人给一支队伍投票,使这个人改变主意需要花费val元,
问为使1号队伍获胜,最少需要花费多少元?

枚举1号队获胜所需的票数

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int MAXN = 3009;
int n, m;
struct node
{
    int id, val;
}a[MAXN];
int has[MAXN], ticket[MAXN];

bool cmp(node a, node b)
{
    return a.val < b.val;
}
int main()
{
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d %d", &a[i].id, &a[i].val);
        has[a[i].id] ++;
    }
    sort(a + 1, a + 1 + n, cmp);

    ll Sum = 0; /// 在所有票数比1号高的队里,共需要买多少票
    ll ans = 999999999999;
    ll tmp = 0;
    for(int i = has[1]; i <= n; i++) /// 枚举1获胜所需票数
    {
        Sum = 0;
        tmp = 0;
        for(int j = 2; j <= m; j++)  /// 列举m个队,看它是否得票比i高(即比1号获胜所需的票数高)
        {
            if(has[j] >= i)
            {
                ticket[j] = has[j] - i + 1;  /// 要在这个队买的票数
                Sum += ticket[j];
            }
            else
                ticket[j] = 0;
        }
        if(i - has[1] < Sum)  /// 最多只能买(i-has[1]), 而实际所需为Sum, 无法购买到Sum张票,此i不可取
            continue;
        Sum = i - (has[1] + Sum);  /// 原有has[1]张票,从比1队高的队里买了Sum张票,还需要i-(has[i]+Sum)张票,还需要的票数从比1队得票少的队里买

        for(int j = 1; j <= n; j++)
        {
            if(a[j].id == 1)  /// 如果第j个人投1号
                continue;

            if(ticket[a[j].id] != 0)   /// 如果j投的队得票比1队高,则需要从第j个人所投的队买票
            {
                tmp += a[j].val;   /// 买j的票
                ticket[a[j].id] --;
            }
            else if(Sum != 0)  /// 如果j投的队得票比1队低,并且需要从得票低的队里买票
            {
                Sum --;
                tmp += a[j].val;
            }
        }
        ans = min(ans, tmp);   /// 记录最小需要花的钱
    }
    printf("%lld\n", ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值