zoukankan      html  css  js  c++  java
  • ZOJ

    ZOJ - 3715KindergartenElection

      题目大意:幼儿园里正在举办班长选举,除1号小朋友外每个人都会投他最好的朋友,但1号小朋友可以贿赂别人(小伙子有丶想法),被贿赂的小朋友就会把票投给1号小朋友而不是他最好的朋友,对于不同的小朋友贿赂的花费也不同,1号小朋友想要自己是唯一的班长(票数最高),问他最少需要花费多少糖果?

      由题目来想,很容易想到贪心,但是不知道怎么贪心。如果是简单让1号是票数最高的小朋友,他每次贿赂都有两种选择,一种是贿赂花费小的人来投他,另一种是贿赂票数比他高的小朋友的投票者中花费小的,如果这两种情况是同一个人的话,那还好说,但如果不是的话,那就不好判断了。所以我们转换思路,我们枚举1号小朋友能得到的票数为x,那么其他小朋友的票数应该小于x,否则1号小朋友应该贿赂他的投票者中一部分花费小的来让他的票数小于x,而如果那一部分贿赂完后,如果1号小朋友的票数大于x,那说明x这个票数是不合理的,1号小朋友应该得到多于x的票才能唯一最多票。而如果还不够x应该在剩下的小朋友里贿赂花费小的来达到x,然后更新答案。

     1 #include<cstdio>
     2 #include<queue>
     3 using namespace std;
     4 priority_queue<int,vector<int>,greater<int> > q[118],p,temp;//由小到大的优先队列 
     5 int fri[118];
     6 int main()
     7 { 
     8     int t,n,x;
     9     scanf("%d",&t);
    10     while(t--)
    11     {
    12         scanf("%d",&n);
    13         while(q[1].size())//每次要先把队列清空 
    14             q[1].pop();
    15         for(int i=2;i<=n;i++)
    16         {
    17             while(q[i].size())
    18                 q[i].pop();
    19             scanf("%d",&fri[i]);
    20         }
    21         for(int i=2;i<=n;i++)
    22         {
    23             scanf("%d",&x);
    24             q[fri[i]].push(x); 
    25         }
    26         int ans=0x3f3f3f3f;
    27         //1号小朋友能得到的票数范围就是已经有的票数到n-1票数 
    28         for(int i=q[1].size();i<=n-1;i++)
    29         {
    30             int cost=0,num=0;
    31             while(p.size())
    32                 p.pop();//p储存没有被贿赂的小朋友 
    33             for(int j=2;j<=n;j++)
    34             {
    35                 temp=q[j];
    36                 //如果这位小朋友的票数大于等于i那么应该把多的先贿赂了 
    37                 while(temp.size()>=i&&temp.size())
    38                 {
    39                     num++;
    40                     cost+=temp.top();
    41                     temp.pop(); 
    42                 }
    43                 //剩下的储存到没被贿赂的小朋友里 
    44                 while(temp.size())
    45                 {
    46                     p.push(temp.top());
    47                         temp.pop();
    48                 }
    49             }
    50             //如果当前的票数还没达到i则补够 
    51             while(q[1].size()+num<i&&p.size())
    52             {
    53                 num++;
    54                 cost+=p.top();
    55                 p.pop();
    56             }
    57             //当好等于i说明i这个答案合理 
    58             if(q[1].size()+num==i&&cost<ans)
    59                 ans=cost;
    60         }
    61         printf("%d
    ",ans);
    62     }
    63     return 0;
    64 }
    优先队列
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<algorithm>
     5 using namespace std;
     6 vector<int> v[118],vv;
     7 int fri[118],cdy[118],book[118];
     8 bool cmp(const int &a,const int &b){
     9     return cdy[a]<cdy[b];
    10 }//按贿赂的糖果数由小到大排 
    11 int main()
    12 { 
    13     int t,n,x;
    14     scanf("%d",&t);
    15     while(t--)
    16     {
    17         scanf("%d",&n);
    18         vv.clear();
    19         v[1].clear();
    20         for(int i=2;i<=n;i++)
    21         {
    22             v[i].clear();
    23             book[i]=0;
    24             scanf("%d",&fri[i]);
    25         }
    26         for(int i=2;i<=n;i++)
    27         {
    28             scanf("%d",&cdy[i]);
    29             v[fri[i]].push_back(i);
    30             if(fri[i]!=1)//vv储存没有把票投给1号小朋友的小朋友 
    31                 vv.push_back(i);
    32         }
    33         //因为贪心嘛,都先按花费由小到大排 
    34         sort(vv.begin(),vv.end(),cmp);
    35         for(int i=2;i<=n;i++)
    36             sort(v[i].begin(),v[i].end(),cmp);
    37         int ans=0x3f3f3f3f;
    38         for(int i=v[1].size();i<=n;i++)
    39         {
    40             int cost=0,num=0;
    41             memset(book,0,sizeof(book));
    42             for(int j=2;j<=n;j++)
    43                 if(v[j].size()>=i)
    44                     for(int k=0;k<v[j].size()-i+1&&k<v[j].size();k++)
    45                     {
    46                         cost+=cdy[v[j][k]];
    47                         book[v[j][k]]=1;
    48                         num++;
    49                     }//多于i的部分先贿赂掉,并标记已经贿赂过了 
    50             for(int j=0;j<vv.size()&&num+v[1].size()<i;j++)
    51             {
    52                 if(book[vv[j]])
    53                     continue;
    54                 cost+=cdy[vv[j]];
    55                 num++;
    56             }
    57             if(num+v[1].size()==i&&cost<ans)
    58                 ans=cost;
    59         }
    60         printf("%d
    ",ans);
    61     }
    62     return 0;
    63 }
    vector标记
  • 相关阅读:
    PAT (BL) 1001
    mysql启动报错:/usr/bin/mysqld_safe: line 183: 17006 Killed nohup /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin......
    动态规划:某个单词增加,删除,替换字母而成为另一个单词的最小变更次数?
    ng-class最好用的一种方法
    java数据结构基本框架
    后台运行tomcat和mysql的方法
    mysql无法开启,报错:MySQL Daemon failed to start.
    linux CentOS6.5 yum安装mysql 5.6
    idea mybatis报错:<statement> or DELIMITER expected, got 'id'
    angularjs $http与springmvc @RequestBody
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/10620976.html
Copyright © 2011-2022 走看看