Kindergarten Election(枚举+贪心)

来源:互联网 发布:java图形界面布局 编辑:程序博客网 时间:2024/04/27 15:18

http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=88#problem/F

题意: 在幼儿园里..每个小朋友投一票选举领导,得票最多的小朋友成为领导(若有多个..则多个领导)。现在有个小朋友相当唯一的领导,即他得到的票数是最多的,没有之一,于是准备贿赂一些小朋友。有n个小朋友,他的编号是1,现在给出编号是2~n的小朋友要投票的对象(即对应的编号),以及它贿赂2~n小朋友需要的糖果。问他能当上班上需要贿赂的最少糖果数。


思路:由于N比较小。数组num[i]表示每个小朋友的得票数。可以对第一个小朋友的得票数 t 进行枚举,范围 num[1] <= t <=n,

对于其余小朋友,若他的得票数num[i] >= t,那么应该从他那拿出 num[i]-(t-1)票给这个小朋友。这是拉票时有个规则,应该拿出需要糖果数较小的票(可以拿个辅助数组,排序一下)。若最后计算出这个小朋友得票数大于之前的枚举值t,说明t值较小,继续下次枚举。否则,再从未投第一个小朋友的人中依次选出较小的知道他的票数满足t.

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int maxn = 110;const int INF = 0x3f3f3f3f;int vote[maxn],num[maxn];int cost[maxn];bool vis[maxn];int tmp[maxn];int n;int cmp(int a, int b){return cost[a] < cost[b];}int main(){int test;int res;scanf("%d",&test);while(test--){memset(num,0,sizeof(num));res = INF;scanf("%d",&n);for(int i = 2; i <= n; i++){scanf("%d",&vote[i]);num[ vote[i] ]++;}for(int i = 2; i <= n; i++)scanf("%d",&cost[i]);for(int t = max(num[1],1); t <= n; t++){int h = num[1];int ans = 0;memset(vis,false,sizeof(vis));for(int i = 2; i <= n; i++){if(num[i] >= t){h += num[i]-(t-1);int cnt = 0;for(int j = 2; j <= n; j++)if(vote[j] == i) tmp[++cnt] = j;sort(tmp+1,tmp+1+cnt,cmp);for(int j = 1; j <= num[i]-t+1; j++){ans += cost[ tmp[j] ];vis[ tmp[j] ] = true;}}}if(h > t) continue;int cnt = 0;for(int i = 2; i <= n; i++){if(!vis[i] && vote[i] != 1)tmp[++cnt] = i;}sort(tmp+1,tmp+1+cnt,cmp);for(int i = 1; i <= t-h; i++)ans += cost[ tmp[i] ];res = min(res,ans);}printf("%d\n",res);}return 0;}



0 0
原创粉丝点击