题目: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;
}