当前位置: 代码迷 >> 综合 >> ZOJ3715Kindergarten Election(贪心+枚举)
  详细解决方案

ZOJ3715Kindergarten Election(贪心+枚举)

热度:88   发布时间:2023-12-06 19:49:53.0

题目大意:

n个小朋友选老大,给出除了一号小朋友外的所有人投票情况,已经1号小朋友需要贿赂i号小朋友来投他自己的花费。1号小朋友希望当老大,并且自己也需要投一票。问最小的花费。


分析:

枚举1号小朋友当选时的得票数。先把票数高于1号的小朋友用贿赂降下来,如果自己票数不够,则选择最小贿赂费的人贿赂。然后检查一遍第二个人到最后一个人的票数是否小于等于当前枚举值-1,并且需要其中一个小朋友的票数小于当前枚举值-1,因为1号小朋友也需要投一票。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 105;
struct Node
{int cost, to;bool use;bool operator < (const Node &other)const{return cost < other.cost;}
}nd[maxn];
int Get[maxn], vis[maxn], vot[maxn];
int main()
{int T, n, tol;scanf("%d", &T);while(T--){scanf("%d", &n);tol = 0;memset(Get, 0, sizeof(Get));for(int i = 2; i <= n; i++){scanf("%d", &vot[i]);Get[vot[i]]++;}for(int i = 2; i <= n; i++){scanf("%d",&nd[tol].cost);if(vot[i] != 1){nd[tol].to = vot[i];nd[tol].use = false;tol++;}}sort(nd, nd+tol);int ans = 0x3f3f3f3f;for(int i = Get[1]; i <= n-1; i++){int cost = 0;memcpy(vis, Get, sizeof(Get));for(int j = 0; j < tol; j++){if(vis[nd[j].to] >= i){nd[j].use = true;cost += nd[j].cost;vis[nd[j].to]--;vis[1]++;}}for(int j = 0; j < tol && vis[1] < i; j++){if(nd[j].use)continue;cost += nd[j].cost;nd[j].use = true;vis[nd[j].to]--;vis[1]++;}int j;for(j = 2; j <= n; j++)if(vis[j] < i-1)break;if(j <= n && vis[1] == i)ans = min(ans, cost);for(j = 0; j < tol; j++)nd[j].use = false;}cout << ans << endl;}return 0;
}