首都位于四面环山的盆地,周围n个小山构成一个环,每个小山上设立一个岗哨。一旦发现敌人,岗哨点燃烽烟。若两个岗哨所在山峰间没有更高的山峰遮挡,则岗哨可以观察到另一个山峰的烽烟。由于小山是环形的,任意两个小山之间可以通过两条路观察。相邻的岗哨肯定可以观察到对方。请计算能相互观察到烽烟的岗哨对数。
输入:第一行为小山数量,第二行为每个小山高度。
输出:相互观察到的岗哨对数。
样例输入:
5
1 2 4 5 3
样例输出:
7
解题思路:
(1)相邻可以相互观察,则n个岗哨至少有n对满足条件的岗哨对。
(2)对于不相邻的哨岗,若下一个岗哨比当前岗哨矮,则记录为max,继续往下寻找,每找到一个高于max的就计数加1,直到比当前岗哨高或寻找结束。
(3)从第i个岗哨开始,依次单向循环寻找满足条件(2)的岗哨,由于(1)中已经计算过相邻的岗哨对,所以单向循环是从(i+1+n)%n到(i-2+n)%n。
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
int temp;
vector<int> circle;
cin >> n;
int count=n; //相邻峰之间都满足
//输入
for(int i=0;i<n;i++){
cin >> temp;
circle.push_back(temp);
}
//计算隔峰狼烟数
for(int i=0;i<n;i++){ //从第i个烽火台开始单向寻找
int j=(i+1+n)%n; //从下一个烽火台开始
int max=circle[j];
while(j!=i-1){ //即使循环后j=i-1符合条件,也在刚开始时相邻边计算过,所以循环到i-2即可
if(circle[j]>max){<span style="white-space:pre"> </span>//找到比中间山峰更高的即计数
max=circle[j];
count++;
}
if(circle[j]>=circle[i])<span style="white-space:pre"> </span>//若比起始山峰还高,则停止起始山峰开始的循环
break;
j=(j+1)%n;
}
}
cout << count << endl;
}