烽火传信问题

【题目】
小B负责首都的防卫工作。
首都处于一个四面环山的盆地中,周围的n个小山构成一个环,作为预警措施,小B计划在每个小山上设置一个观察哨,日夜不停的瞭望周围发生的情况。
一旦发生外敌入侵事件,山顶上的岗哨将点燃烽烟。
若两个岗哨所在的山峰之间的那些山峰,高度都不大于这两座山峰,且这两个山峰之间有相连通路,则岗哨可以观察到另一个山峰上的烽烟是否点燃。
由于小山处于环上,任意两个小山之间存在两个不同的连接通路。满足上述不遮挡的条件下,一座山峰上岗哨点燃的烽烟至少可以通过一条通路被另一端观察到。
对于任意相邻的岗哨,一端的岗哨一定可以发现一端点燃的烽烟。
小B设计的这种保卫方案的一个重要特性是能够观测到对方烽烟的岗哨对的数量,她希望你能够帮她解决这个问题。
输入
输入中有多组测试数据。每组测试数据的第一行为一个整数n(3<=n<=10^6),为首都周围的小山数量,第二行为n个整数,依次表示小山的高度h,(1<=h<=10^9)。
输出
对每组测试数据,在单独的一行中输出能相互观察到的岗哨的对数。
样例输入
5
1 2 4 5 3
样例输出
7

解决方法:向节点的两边寻找最靠近的且大于该节点的,即为一组岗哨对。可以构建一个双向循环链表存储数据,双向遍历寻找符合要求的值。代码如下:
 

import java.util.Scanner;

class Node{
	int value;
	Node next;
	Node behind;
	Node(){}
	Node(int value) {
		this.value = value;
	}
}
class DoubleLinkedList{
	public static Node head ;
	public DoubleLinkedList() {
		 head = new Node();
		 head.value = 0;
		head.next = head;
		head.behind = head;
	}

	
	public static Node add(int value) {
		if(head.value ==0) {
			head.value = value;
			return head;
		}
		Node node  = new Node(value);
		
		head.behind.next = node;
		node.behind = head.behind;
		node.next = head;
		head.behind = node;
		return head;
	}
	
}

public class Mountain{
	
	
	public static void main(String[] args) {
		DoubleLinkedList linkedlist = new DoubleLinkedList();
		Node head = linkedlist.head;
			 Scanner sc = new Scanner(System.in);
			 int n  = sc.nextInt();
			// int[] arr = new int[n];
			 for(int i = 0;i < n;i++) {
				head =  linkedlist.add(sc.nextInt());
			 }
			 Node node = new Node();
			 node = head;
			 Node next = new Node();
			 Node pre  = new Node();
			 int num = 0;
			 for(int i = 0;i < n;i++) {
			/*	 System.out.print(node.value + " "); 
				 node = node.next;*/
				 next = node.next;
				 pre = node.behind;
				/* while(next !=pre) {
					while(node.value>next.value) {
						num++;
						if(node.next != next)
							num++
					}
					if(node.value < next.behind.value) {
						num++;
						if(node.behind!=pre)
							num++;
					}
				 }*/
				while(next.value<node.value && next !=node) {
					next = next.next;
				}
				if(next!=node) {
				System.out.println(node.value+ " "+next.value);
				num++;}
				while(pre.value<node.value && pre!=node) {
					pre = pre.behind;
				}
				if(pre != node && pre !=next) {
				System.out.println(node.value + " " + pre.value);
				num++;
				}
				System.out.println(num);
				node = node.next;
					 
				 }
			 sc.close();	
			 }
			/* System.out.println();
			 for(int i=0;i < n; i++) {
				 System.out.print(node.value+ " ");
				 node = node.behind;
			 }*/
			
			 
	
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值