• Codeforces Round #311 (Div. 2)


    Problem:A(557A). Ilya and Diploma (贪心)

    题目大意:

      学校要举办运动会,有n个学生参加,为了鼓励学生主办方一共颁发n个证书,保证每人一本,有三种证书,每个证书都有一个颁发数目的区间,在满足上面的条件下,尽量A证书最多,B证书次之,C证书能多则多,问最后颁发三种证书各多少本?

    解题思路:

      先对三类证书分别颁发min本,还有学生没有证书的话,就对没有证书的同学按照A,B,C的顺序进行贪心。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int main ()
     4 {
     5     int n;
     6     while (scanf ("%d", &n) != EOF)
     7     {
     8         int a[3][2], num[3];
     9         for (int i=0; i<3; i++)
    10         {
    11             scanf ("%d %d", &a[i][0], &a[i][1]);
    12             num[i] = a[i][0];
    13             a[i][1] -= a[i][0];
    14             n -= a[i][0];
    15         }
    16         for (int i=0; i<3 && n>0; i++)
    17         {
    18             num[i] += min (n, a[i][1]);
    19             n -= a[i][1];
    20         }
    21         printf ("%d %d %d
    ", num[0], num[1], num[2]);
    22     }
    23     return 0;
    24 }

    Problem:B(557B). Pasha and Tea (sort)

    题目大意:

      有一壶开水Wml,现在有n个男生,n个女生,有2*n个杯子(杯子容量各不相同),要求在不溢出的情况下,给男生倒的水是女生的二倍,而且n个男生得到的水一样多,n个女生得到的水也一样多,问最多可以消耗多少ml水?

    解题思路:

      可以先对2*n个杯子的容量进行排序,女生肯定是用n个较小的杯子,男生用n个较大的杯子,因为男生,女生得到的水一样多,所以他们得到的水由他们所分到的杯子里面最小的决定,(PS:消耗的水不能比水壶的容量大)。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 200005;
     4 int main ()
     5 {
     6     int n;
     7     double m, a[maxn];
     8     while (scanf ("%d %lf", &n, &m) != EOF)
     9     {
    10         for (int i=0; i<2*n; i++)
    11             scanf ("%lf", &a[i]);
    12         sort (a, a+2*n);
    13         double num = min (a[0], a[n]/2) * 3 * n;
    14         num = min (num, m);
    15         printf ("%f
    ", num);
    16     }
    17     return 0;
    18 }

    Problem:C(557C). Arthur and Table (sort+模拟)

    题目大意:

      一个桌子有n条腿(八脚怪究极进化体),现在需要移除一些桌子腿使桌子变平稳(平稳是有一半以上的桌子腿的长度是未移除桌子腿中最长的),每移除一条桌子腿需要花费精力,问最少花费多少精力才能让桌子平稳?

    解题思路:

      先对所有的桌子腿按照按照长度升序排列,然后枚举每个出现过的长度作为使桌子平稳的桌子腿中最长的,求出所花费精力,比较得出最小。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 100005;
     4 const int N = 210;
     5 struct Leg
     6 {
     7     int l, d;
     8 }leg[maxn];
     9 bool cmp (Leg x, Leg y)
    10 {
    11     return x.l < y.l;
    12 }
    13 int main ()
    14 {
    15     int n;
    16     while (scanf ("%d", &n) != EOF)
    17     {
    18         int cnt[N], total = 0;
    19         memset (leg, 0, sizeof(leg));
    20         memset (cnt, 0, sizeof(cnt));
    21         
    22         for (int i=0; i<n; i++)
    23             scanf ("%d", &leg[i].l);
    24         for (int i=0; i<n; i++)
    25         {
    26             scanf ("%d", &leg[i].d);
    27             total += leg[i].d;
    28         }
    29         
    30         sort (leg, leg+n, cmp);
    31         
    32         int Min, num, index, cost, i;
    33         Min = total;
    34         i = 0;
    35         
    36         while (i < n)
    37         {
    38             index = i;
    39             cost = total;
    40             num = 0;
    41             while (index<n && leg[i].l==leg[index].l)
    42             {//枚举最高leg
    43                 cost -= leg[index++].d;
    44                 num ++;
    45             }
    46             num --;
    47             for (int j=200; j>0&&num>0; j--)
    48             {//加入低一点的leg,求出花费
    49                 cost -= min(num, cnt[j])*j;
    50                 num -= cnt[j];
    51             }
    52             Min = min (Min, cost);
    53             index = i;
    54             while (index<n && leg[i].l==leg[index].l)
    55                 cnt[leg[index++].d] ++;//低一点的边加入cnt,以便后面枚举更高的leg时候减小花费
    56             i = index;
    57         }
    58         printf ("%d
    ", Min);
    59     }
    60     return 0;
    61 }

     Problem:D(557D). Vitaly and Cycle (bfs+组合数)

    题目大意:

      由n个顶点和m条边组成的无向图(没有平行边,可能不连通),问最少加入几条边可以形成含有奇数个顶点的环,有几种加边的方法?

    解题思路:

      加边的条数一共有4情况(先用bfs对无向图进行染色处理,颜色为a的只能和颜色为b的相连):

      1:不加边,无向图中含有奇环。

      2:加一条边,无向图中还有有些点的度大于1,这些点所在的连通块里面假设颜色为a的点有x个,颜色为b的有y个,这个连通块里面有C(a,2)+C(b,2)中方法,连通块和连通块之间并不能通过加一条边形成奇环。

      3:加两条边,无向图中点的度最多为一,若要形成奇环,就至少需要加两条边,方法数目为:m * C(n-2, 1);

      4:加三条边,无向图中并没有边,只有n个点,就只能加三条边使得三个独立的点连成奇环,方法数目为:C(n, 3);

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef __int64 LL;
     4 const int maxn = 100005;
     5 struct Edge
     6 {
     7     int to, next;
     8 };
     9 int head[maxn], cnt[maxn], tot;
    10 LL  ans;
    11 Edge edge[maxn*2];
    12 void add (int from, int to)
    13 {//邻接表存边
    14     edge[tot].to = to;
    15     edge[tot].next = head[from];
    16     head[from] = tot++;
    17 }
    18 int bfs (int s)
    19 {
    20     queue<int>Q;
    21     int x, y, p, q, num, nu;
    22     Q.push(s);
    23     y = 0;
    24     cnt[s] = x = 1;
    25     while (!Q.empty())
    26     {
    27         p = Q.front();
    28         Q.pop();
    29         nu = cnt[p] + 1;//cnt[i]为奇数,i点为red,否则i点为black
    30         num = head[p];
    31         while (num != -1)
    32         {
    33             q = edge[num].to;
    34             if (cnt[q] == -1)//未染色
    35                 {
    36                     Q.push(q);
    37                     if (nu % 2)//统计为red,black颜色点的数目
    38                         x++;
    39                     else
    40                         y ++;
    41                     cnt[q] = nu;
    42                 }
    43             else if (cnt[q]%2 == cnt[p]%2)//遇到奇环
    44                 return 1;
    45             num = edge[num].next;
    46         }
    47     }
    48     ans += (LL)x * (x-1) / 2;//没遇到奇环,计算加一条边的方法数目
    49     ans += (LL)y * (y-1) / 2;
    50     return 0;
    51 }
    52 int main ()
    53 {
    54     int n, m;
    55     scanf ("%d %d", &n, &m);
    56         if (m == 0)
    57         {//加三条边
    58             printf ("3 %I64d
    ", (LL)n*(n-1)*(n-2)/6);
    59             return 0;
    60         }
    61         memset (edge, -1, sizeof(edge));
    62         memset (head, -1, sizeof(head));
    63         memset (cnt, 0, sizeof(cnt));
    64         tot = ans = 0;
    65         for (int i=0; i<m; i++)
    66         {
    67             int from, to;
    68             scanf ("%d %d", &from, &to);
    69             add (from, to);
    70             add (to, from);
    71             cnt[from] ++;
    72             cnt[to] ++;
    73         }
    74         int Max = -1;
    75         for (int i=1; i<=n; i++)
    76             Max = max(Max, cnt[i]);
    77         if (Max == 1)
    78         {//加两条边
    79             printf ("2 %I64d
    ", (LL)m * (n-2));
    80             return 0;
    81         }
    82         memset (cnt, -1, sizeof(cnt));
    83         for (int i=1; i<=n; i++)
    84         {
    85             if (cnt[i] == -1)
    86             {
    87                 int res = bfs(i);
    88                 if (res)
    89                 {
    90                     printf ("0 1
    ");
    91                     return 0;
    92                 }
    93             }
    94         }
    95         printf ("1 %I64d
    ", ans);
    96     return 0;
    97 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    创龙DSP6748的DAC例程研究
    LARK BOARD开发板试用第一篇-上电测试学习
    itop-4412开发板使用第一篇-信号量的学习使用
    《王阳明》读书笔记
    【原创】大叔问题定位分享(5)Kafka客户端报错SocketException: Too many open files 打开的文件过多
    【原创】大叔问题定位分享(4)Kafka集群broker节点从zookeeper上消失
    【原创】大叔问题定位分享(3)Kafka集群broker进程逐个报错退出
    【原创】大数据基础之Kafka(1)简介、安装及使用
    【原创】大叔问题定位分享(2)spark任务一定几率报错java.lang.NoSuchFieldError: HIVE_MOVE_FILES_THREAD_COUNT
    【原创】大数据基础之Quartz(1)简介、源代码解析
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4613929.html
Copyright © 2020-2023  润新知