1. 程式人生 > >cf 1020 round 503(SIS div2) C. Elections

cf 1020 round 503(SIS div2) C. Elections

題意:給出n個人投票,開始每個人都有一個選好的人,如果我們要使它換票就必須支付他所給的價格,我們要使1號選手贏得比賽,問我們支付最少的錢是多少來使一號贏得勝利

思路: 我們考慮到純貪心有太多種情況,題目所給的資料也是3000,說明我們可以使用n^2以至更高的演算法,我們考慮1號選手獲勝的狀態,就是他是以幾票來獲得勝利的

列舉獲勝狀態,然後我們取最優的

給一個例子    1:0票        2:3票          3:3票       4:2票         5 :1票

1號選手1票獲取勝利   不存在

2票獲取勝利     不存在

3票獲取勝利     如果我們要三票贏2號和3號,必須要比2號3號多一票才可以,但是我們總共只買三票,既然我們不能增多自己,只能削弱對手,

其中一票在2號這裡買,那麼他就會降為2票,3號同理,然後剩下一票,買價格最低的即可

然後四票五票獲取勝利的方法同理,我們只要取花費價格最少的狀態即可

#include<bits/stdc++.h>
using namespace std;
struct person{
    int p,c;
}per[
3010]; int f[3010]; int g[3010]; bool cmp(person A,person B) { return A.c<B.c; } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&per[i].p,&per[i].c); f[per[i].p]++; } long long res=3e12; sort(per+1,per+n+1
,cmp); for(int i=f[1];i<=n;i++) { int sum=0; for(int j=2;j<=m;j++) { if(f[j]>=i) { g[j]=f[j]-i+1; sum+=g[j]; } else g[j]=0;//此處不可省略, g陣列要反覆更新 } if(i-f[1]<sum) continue; long long ans=0; sum=i-f[1]-sum; for(int j=1;j<=n;j++) { if(g[per[j].p]>0) { g[per[j].p]--; ans+=per[j].c; } else if(sum>0&&per[j].p!=1) { sum--; ans+=per[j].c; } } res=min(ans,res); } printf("%lld\n",res); }