P1047 [NOIP2005 普及组] 校门外的树 题解

文章目录

思路

  考虑结合数学数轴上面的线段知识来解决。有交集时,若在线段范围中,进行范围合并,若超出范围,则进行范围延长;若无交集则单独成段。例如:

  • 输入 #1

      500 3
      150 300
      100 200
      470 471
    
  • 作图如下
    数轴线段图

  • 测试样例
    测试结果

代码

  • C++ 实现
// -*- coding: utf-8 -*-
//  @ Date   : 2020/5/20 13:14
//  @ Author : RichardLau_Cx
//  @ file   : Richard.cpp
//  @ IDE    : Dex-C++
//  @ Source : luogu

#include <iostream>

using namespace std;

int main()
{
	int l;  // 马路长度
	int m;  // 区域的数目
	int index = 0;  // 初始放至于0号索引 
	int add = 0;  // 端点需要移除的树 
	
	cin >> l >> m;
	int points[m+1][2];  // 存放m个区域的起始点坐标,空出一行用来做交换 
	int remainder = l;  // 剩余的树木数量 
	
//	while(m--)
//	{  // 此方法不适合结合重合部分 
//		int u, v;  // 一个区域的起始点和终止点的坐标
//		cin >> u >> v
//	 } 
	 
	 for (int i=0; i < m; i++)
	 {
	 	cin >> points[i][0] >> points[i][1];
	 	/*
	 	if (points[i][0] > points[i][1])
		{  // 考虑到给定的起始位置可能为倒序,如:起始点位置 < 终止点位置时,把顺序调整为升序, => 题目中已经表明:0 <= u <= v <= l
		 	int temp = points[i][0];
			points[i][0] = points[i][1];
			points[i][1] = temp;  
		} 
		*/
	 }
	 
	  
	 for (int i=0; i < m-1; i++)
	 {  // 处理思路:排序 + 判断 
	 
	 	for (int j=0; j < m-1; j++)
		 {
//		 	cout << "here!" << endl;
		 	if (points[j][0] > points[j+1][0])
		 	{
//		 		points[m][0], points[m][1] = points[j][0], points[j][1];
				points[m][0] = points[j][0];			
		 		points[m][1] = points[j][1];
		 		
//				points[j][0], points[j][1] = points[j+1][0], points[j+1][1];
				points[j][0] = points[j+1][0];
				points[j][1] = points[j+1][1];
				
//				points[j+1][0], points[j+1][1] = points[m][0], points[m][1];
				points[j+1][0] = points[m][0];
				points[j+1][1] = points[m][1];
			 }
		  } 
	 	
	 }
	 
	 /* 
	 cout << endl << endl << "begin: " << endl;
	 
	 for (int i=0; i < m; i++)
	 {
	 	cout << points[i][0] << ' ' << points[i][1] << endl;
	 }
	  cout << "end: " << endl << endl << endl;;
	*/
	 
//	 for (int i=0; i < m; i++)
//	 {
//	 	cout << points[i][0] << ' ' << points[i][1] << endl;
//	 }
	 
	 for (int i=1; i < m; i++)
	 {
//	 	cout << "here" << i << endl;
	 	if (points[index][1] >= points[i][0])
	 	{  			
			if (points[index][1] < points[i][1]) 
			{  // 同时左边的终止点小于右边的终止点,扩大范围 
				points[index][1] = points[i][1];
			}
			
			// 证明发生了交集,重复和多余区域置零 
			points[i][0]=0, points[i][1]=0; 
		 }
		 
		else
		{  // 未发生交集,索引后跳 
			index = i; 
			add++; 
		}
	 }
	
	for (int i=0; i < m; i++)
	 {
	 	remainder -= points[i][1] - points[i][0];
	 }
	 
	 
//	 cout << "begin: " << endl;
//	 for (int i=0; i < m; i++)
//	 {
//	 	cout << points[i][0] << ' ' << points[i][1] << endl;
//	 }

//	cout << "remainder: " << remainder-add << endl;
	cout << remainder-add << endl;
	
	return 0;
 } 
 
// TODO : 排序和左右数据调整存在问题,考虑优化排序方式 --- 现已优化 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值