ZOJ 3715 Kindergarten Election

题目大意

意思就是这里有n个小朋友要选一个班长。

每一个小朋友都有一票,小朋友因为害羞不会投自己,只会投给他们最好的同学。现在1号小朋友想要当班长,而且是当唯一的班长,这就意味着他的票数必须要大于其他人的所有票。他可以通过买糖果给其他小朋友让他们把票投给他自己。

现在求1号当上班长需要花费的最小糖果数。

这道题目的思路就是枚举他最小的票数s,然后每次贪心找到每种情况的最小花费。

对于每种情况,都有:

  • 先枚举2-n同学中票数大于等于s的。假设对于同学i有s+6票,那么在这s+6票中,找出花费糖果最小的7票。然后花费这么多糖果来争取他们的票数。
  • 对于1号同学如果经历完第一步票数还不够s票。从剩下的票数中,每次找的最小花费的同学,依次花费糖果。 直到大于等于s票
#include<bits/stdc++.h>
using namespace std;

const int N = 107;
bool visited[N];
pair<int, int>par[N];
vector<int> vec[N];
int n;

int cal(int k)
{
    memset(visited, false, sizeof(visited));

    int ans = 0;
    int s = vec[1].size();

    for(int i=2; i<=n; ++ i)
    {
        if(vec[i].size() >= k)
        {
            for(int j=0; vec[i].size() - j >= k; ++ j)
            {
                int t = vec[i][j];
                ans += par[t].first, visited[t] = true, ++ s;
            }
        }
    }

    if(s < k)
    {
        for(int i=0; i<n-1; ++ i)
        {
            if(visited[i] == false && par[i].second != 1)
                ans += par[i].first, ++ s;

            if(s >= k)
                break;
        }
    }
    return ans;
}

int solve()
{
    cin >> n;
    for(int i=0; i<n-1; ++ i)
        cin >> par[i].second;
    for(int i=0; i<n-1; ++ i)
        cin >> par[i].first;

    sort(par, par+n-1);
    for(int i=1; i<=n; ++ i)
        vec[i].clear();
    for(int i=0; i<n-1; ++ i)
        vec[par[i].second].push_back(i);

    int ans = INT_MAX;
    for(int i = max((int)vec[1].size(), 1); i<=n-1; ++ i)
    {
        ans = min(ans, cal(i));
        //cout << i << ":" << ans << endl;
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);

    int t;
    cin >> t;
    for(int i=1; i<=t; ++ i)
        cout << solve() << endl;
    return 0;
}

转载于:https://www.cnblogs.com/aiterator/p/6786623.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值