zoukankan      html  css  js  c++  java
  • 修路&&牛.. 贪心+二分..

    主要是两种贪心+二分的方法..

    可以看作是入门题..

    牛..

    题意:

    输入:

    L(河的长度l) N(河上有n个石子) M(可以移动的最多的石子数m)

    往下n行表示河上的石子离左河岸的距离

     

    输出:

    所有 移动了m个石子后最短距离 的最大值..

    思想..

    其实牛可以跳的距离就在最大就是河的长度..

    所以可以用二分的方法看看小于河的长度内可以跳的最大长度..

     

    ***贪心通常用一个check()函数来判断***

    check()

    判断每一个點到上一个點的距离是否小于假定的最短距离的最大值..

    如果是就count加1..

    如果不是就把上一个點的坐标替换成当前點坐标..

    最后判断是不是在m内..

    ******************************

    如果不是意味着點之间的距离太大了..所以要往左移..

    是就往右移..

     

    往左右移就用二分..

    速度能比较快了..

    Code:

    View Code
     1 #include <stdio.h>
     2 #include <cstring>
     3 #include <stdlib.h>
     4 
     5 int l, n, m;
     6 int dis[50010], len, count;
     7 int top, low, mid;
     8 
     9 bool check()
    10 {
    11     int pos = count = 0;
    12     int i;
    13     for(i = 1; i <= n+1; ++i)
    14     {
    15         if(dis[i] - pos < mid)
    16             count++;
    17         else pos = dis[i];
    18     }
    19     return count > m;
    20 }
    21 
    22 int cmp(const void *a, const void *b)
    23 {
    24     return *(int *)a - *(int *)b;
    25 }
    26 
    27 int main()
    28 {
    29     int i, j, k = 0;
    30     while(scanf("%d %d %d", &l, &n, &m) != EOF)
    31     {
    32         dis[0] = 0, dis[n+1] = l;
    33         for(i = 1; i <= n; ++i)
    34         scanf("%d", &dis[i]);
    35 
    36         qsort(dis, n+1, sizeof(dis[0]), cmp);
    37 
    38         top = l, low = 1;
    39         while(top >= low)
    40         {
    41             mid = (top + low)/2;
    42 //printf("%d : mid: %d top: %d low: %d", k++, mid, top, low);
    43             if(check()) top = mid - 1;
    44             else low = mid + 1;
    45 //printf(" count: %d\n", count);
    46         }
    47         printf("%d\n", low-1);
    48     }//while cin l n m
    49     return 0;
    50 }//1006

    ==================================================================

    ==================================================================

    修路的思路和牛差不多..

    输入:

    T(T组样例..)

    m(m条路段) n(n支队伍..)

    接下来m个路段代表每个路段长度..

    PS:每个队伍可以修一条或连续的几条路段..

     

    输出:

        所有队伍同时开工..最后都结束的时间..

    思路:

    贪心找出可以修的最长路段..

     

    ***check()函数****************

    判断遍历的路段的长度和前一个相加是否小于猜测的构造队伍最少花的时间...

    如果是就继续加..

    如果不是就从这个點重新累加..并且计算如果按这个预期算总共要用多少支队伍....

    根据用的队伍数和给出的队伍数多少来判断..

    ****************************

    如果按这个预期得到的队伍数比给出的队伍数多了就代表预期短了..

    注意二分的时候top给的时候不是top-1..而是top..

    Code:

    View Code
     1 #include <stdio.h>
     2 #include <cstring>
     3 #define INF 0x1f1f1f1f
     4 
     5 int T, m, n;
     6 int dis[1010];
     7 int top, low, mid;
     8 
     9 bool check()
    10 {
    11    int sum = 0, count = 1;///!!!
    12    for(int i = 0; i < n; ++i){
    13    if(dis[i] + sum <= mid){
    14    sum += dis[i];
    15 
    16    }
    17    else{
    18       sum = dis[i];
    19       count++;
    20      }
    21    }
    22   return count <= m;
    23 }
    24 
    25 int main()
    26 {
    27   int i, j, k;
    28   int max, min;
    29   while(scanf("%d", &T) != EOF)
    30   while(T--)
    31   {
    32     max = 0;
    33     min = 0;
    34     scanf("%d %d", &n, &m);
    35     for(i = 0; i < n; ++i){
    36       scanf("%d", &dis[i]);
    37       max += dis[i];
    38       if(dis[i] > min) min = dis[i];
    39     }
    40 
    41     top = max, low = min;
    42     while(top > low)
    43     {
    44       mid = (top + low)/2;
    45       if(check()) top = mid;///??
    46       else low = mid + 1;
    47     }
    48 
    49     printf("%d\n", low);
    50   }
    51   return 0;
    52 }
  • 相关阅读:
    【2017-4-26】Winform 公共控件 菜单和工具栏
    【2017-4-24】Winform 简单了解 窗口属性
    【2017-4-21】ADO.NET 数据库操作类
    【2017-4-21】ADO.NET 防止字符串注入攻击
    【2017-4-19】ADO.NET 数据库链接,基础增删改
    Vue#条件渲染
    Vue#Class 与 Style 绑定
    Vue#计算属性
    Vue入门笔记#数据绑定语法
    Vue入门笔记#过渡
  • 原文地址:https://www.cnblogs.com/Griselda/p/2590870.html
Copyright © 2011-2022 走看看