ZOJ 3715 - Kindergarten Election 枚举后贪心...

             题意:

                      在幼儿园里..每个小朋友投一票选举领导...得票最多的小朋友成为领导(若有多个..则多个领导)..现在有个小朋友相当唯一的领导..于是准备贿赂一些小朋友..让他们把票投给自己...每个小朋友要买通..必须满足给他的糖数...问这个小朋友最少用多少的糖使得他成为唯一的leader~

             题解:

                      今天做的练习赛里的...比赛中各种没想法..想DP..但状态无法表示...想贪心..但一直没找到一个明确的方法...好乱...

                      这种模式的题目感觉没做过什么...由于数据范围不大...先枚举咱们这个小朋友是拿的多少个糖赢的..记为t...然后让其他的小朋友糖数小于t(大于t的.则减少到t-1)..而改变这些必然把选票加到自己头上来..寻则所需糖数最少的来操作...当所有小朋友的票数<t了..看咱这个1号小朋友..若他得到的票数大于了t..枚举失败..继续往更大的t进行枚举..若等于t..那么就已经得到了当前枚举条件下的最佳方案..若<t...则需要将还未买通的小朋友中糖数需求最小的几个给买通..让其票数正好等于t...

                      这道题还有个问题是1号小朋友要向别人投票...向票数最少的投就行了..又不可能所有的小朋友票数为t-1( t+(t-1)*(N-1)=N无整数解)...所以这个其实不用考虑..


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#include<algorithm>
#define ll long long
#define eps 1e-5
#define oo 1<<30
#define pi acos(-1.0)
#define MAXN 105
using namespace std;   
int f[MAXN],v[MAXN],sum[MAXN],id[MAXN];
bool used[MAXN];
bool cmp(int a,int b) { return v[a]<v[b]; }
int main()
{                
       int T,n,i,ans;    
       scanf("%d",&T);
       while (T--)
       {
               scanf("%d",&n);      
               memset(sum,0,sizeof(sum));
               for (i=2;i<=n;i++) scanf("%d",&f[i]),sum[f[i]]++;
               for (i=2;i<=n;i++) scanf("%d",&v[i]);
               ans=oo;
               for (int t=max(sum[1],1);t<n;t++)
               {
                       int data=0,x,num,h=sum[1];
                       memset(used,false,sizeof(used));
                       for (i=2;i<=n;i++)
                          if (sum[i]>=t)
                          {
                                h+=sum[i]-(t-1);
                                if (sum[1]>t) break;
                                num=0;
                                for (x=2;x<=n;x++)
                                   if (f[x]==i) id[++num]=x;
                                sort(id+1,id+1+num,cmp);
                                for (x=1;x<=sum[i]-(t-1);x++) data+=v[id[x]],used[id[x]]=true;
                          }
                       if (sum[1]>t) continue;
                       num=0;
                       for (x=2;x<=n;x++)
                          if (!used[x]) id[++num]=x;
                       sort(id+1,id+1+num,cmp);
                       for (i=1;i<=t-h;i++) data+=v[id[i]];
                       ans=min(ans,data);
               }               
               printf("%d\n",ans);
       }
       return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值