P1047 [NOIP2005 普及組] 校門外的樹 題解
阿新 • • 發佈:2021-01-29
技術標籤:ACM 演算法分析與設計演算法c++acm競賽c演算法陣列
文章目錄
思路
考慮結合數學數軸上面的線段知識來解決,例如:
-
輸入 #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 : 排序和左右資料調整存在問題,考慮優化排序方式 --- 現已優化