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