题意:给出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); }
原文地址:https://www.cnblogs.com/lishengkangshidatiancai/p/10264066.html
时间: 2024-11-05 15:53:39