线段覆盖问题(贪心算法)

Problem Description

给出x轴上N条线段的坐标,从中选择一些线段来覆盖住区间[0,M],要求所用线段数目最少。

Input Description

第一行输入两个整数0<N<10000,0<M<1000000,分别表示线段的数量和需要覆盖的区间[0,M]。
接下来N行,每行输入两个整数,分别表示第i条线段的左端点和右端点。

Output Description

在一行中输出 "the answer is 所选线段数量"。
若无解则输出 "wrong!"

Sample Input

3 1
-1 0
-5 -3
2 5

6 4
-1 0
-1 1
0 3
2 4
2 5
4 5

Sample Output

wrong!

the answer is 2

个人分析:

解决本题使用的是贪心算法

首先我们需要将数据进行排序,排序是基于线段的左端点进行排序的,将左端点,由小到大进行排序(我是用的插空排序)

然后,在线段的左端满足last_right的情况下,选择右端尽可能最长的线段进行覆盖(设置一个noew_right代表已经覆盖的线段的右端,因为now_right是不断更新的,所以用last_right记录上一次的now_right)。

#include<stdio.h>

typedef struct Line
{
  int left;
  int right;
}Line;

void sort(Line a[], int n)
{
  for(int i = 1; i < n; i++)
  {
      Line tmp = a[i];
      int j = i - 1;
      while(a[j].left > tmp.left && j >= 0)
      {
          a[j + 1] = a[j];
          j--;
      }
      a[j + 1] = tmp;
  }
}
int main()
{
    int n, m;
   while(scanf("%d %d", &n, &m) != EOF)
   {
        Line line[n];
        Line tmp[n];
       for(int i = 0; i < n; i++)
       {
          scanf("%d %d", &line[i].left, &line[i].right);
       }
       for(int i = 0; i < n; i++)
       {
          tmp[i] = line[i];
       }

       int num = 0;
       sort(line, n);
       int last_right = 0, now_right = 0;
       int i = 0;
       int e = 0;
       while(now_right < m)
       {
           last_right = now_right;
          while(i < n && line[i].left <= last_right)
          {
             if(line[i].right > now_right)
             {
                now_right = line[i].right;
             }
             i++;
          }
          num++;
          e++;
          if(i == n && now_right < m || now_right == last_right)
          {
            break;
          }
       }
       if(now_right < m)
       {
          printf("wrong!\n");
       }
       else
       {
          printf("the answer is %d\n", num);
       }

   }

  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值