sky line 问题的一种解决思路(附部分源代码)(NJAU网工)

//南京农业大学,网工
package algorithm;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.BufferedReader;

class Item
{
	public int x;
	public int lh;
	public int rh;
	public Item()
	{
		this.rh=this.lh=0;
	}
}

class Queue
{
	public Item items[];//
	public int cnt;
	public Queue()//构造
	{
		cnt=0;
		this.items=new Item[100];
		for(int i=0;i<100;i++)
		{
			this.items[i]=new Item();
		}
		
	}
	public boolean insert(int j,int x,int h)
	{
		//如果在j为插入的x和前面那位的x重合,那么只需要更新即可
		if(j!=0&&this.items[j-1].x==x)
		{
			this.items[j-1].rh=h;
			this.items[j].lh=h;
			this.show();
			return false;
		}
		//如果在第0位插入
		if(j==0)
		{
			for(int i=99;i>j;i--)
			{
				this.items[i].lh=this.items[i-1].lh;
				this.items[i].rh=this.items[i-1].rh;
				this.items[i].x=this.items[i-1].x;
				//System.out.println(""+i+" "+this.items[i].x+" "+this.items[i].rh);
			}
			//System.out.println("j="+j);
			this.items[j].x=x;
			this.items[j].lh=0;
			this.items[j].rh=h;
			this.items[j+1].lh=h;
			cnt++;
			this.show();
			return true;
		}
		for(int i=99;i>j;i--)
		{
			this.items[i].lh=this.items[i-1].lh;
			this.items[i].rh=this.items[i-1].rh;
			this.items[i].x=this.items[i-1].x;
		}
		this.items[j].x=x;
		this.items[j].lh=this.items[j-1].rh;
		this.items[j].rh=h;
		this.items[j+1].lh=h;
		cnt++;
		this.show();
		return true;
	}
	public void show()
	{
		System.out.println("this is show!");
		for(int i=0;i<this.cnt;i++)
		{
			System.out.print("#"+i+" "+this.items[i].lh+" "+this.items[i].x+' '+this.items[i].rh+" ----");
		}
		System.out.println("");
	}
	public void clear()
	{
		for(int i=0;i<this.cnt;i++)
		{
			int hh=this.items[i].rh;
			while(true)
			{
				if(this.items[i+1].rh!=hh||this.items[i+1].x==100)
				{
					break;
				}
				this.deleteItem(i+1);
			}
			if(this.items[i+1].x==100)
			{
				break;
			}
		}
	}
	public void deleteItem(int j)
	{
		for(int i=j;i<99;i++)
		{
			this.items[i]=this.items[i+1];
		}
		this.cnt--;
	}
}
class SItem
{
	public int lx;
	public int rx;
	public int h;
}

class SQueue
{
	public SItem sitems[];
	public int cnt;
	public SQueue() throws IOException
	{
		cnt=0;
		sitems=new SItem[100];
		for(int i=0;i<100;i++)
		{
			this.sitems[i]=new SItem();
		}
		//BufferedInputStream bs=new BufferedInputStream(new FileInputStream("data.txt"));
		BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("data.txt")));
		String str=br.readLine();
		while(str!=""&&str!=null)
		{
			//先分解出来三个东西
			String  a,b,c;
			int index1,index2;
			index1=str.indexOf(' ');
			index2=str.indexOf(' ',index1+1);
			a=str.substring(0,index1);
			b=str.substring(index1+1,index2);
			c=str.substring(index2+1,str.length());
			//此处分界完毕
			this.sitems[cnt].lx=Integer.parseInt(a);
			this.sitems[cnt].h=Integer.parseInt(b);
			this.sitems[cnt].rx=Integer.parseInt(c);
			cnt++;
			str=br.readLine();
		}
	}
	
	
}

public class Buildings {

	public static void main(String[] args)throws IOException 
	{
		// TODO Auto-generated method stub
		
		//循环加入SQueue中的元素
		int i=0;
		SQueue sq=new SQueue();
		Queue q=new Queue();
		boolean flag=true;
		for(i=0;i<sq.cnt;i++)
		{
			//此时提取出第一个
			SItem si=sq.sitems[i];
			//遍历queue,如果没有元素,那么直接加入queue之中,在合适的位置
			if(q.cnt==0)
			{
				q.items[0].lh=0;
				q.items[0].rh=0;
				q.items[0].x=1;
				q.items[1].lh=0;
				q.items[1].rh=0;
				q.items[1].x=100;
				q.cnt=2;
			}
			int j=0;
			for(j=0;j<q.cnt;j++)//此循环遍历queue
			//如何确定需要再后面增加呢?
			{
				int hh=q.items[j].lh;
				//遇到第一个小于之处,停下来
				if(si.lx<q.items[j].x)
					//表明我和你这个矩形有交集,而且是第一个交集的矩形
				{
					//分别比较该点左右两边的高度
					//先看左边,如果我小于等于左边的,是我被隐没了,直接把我裁剪剩下右半部分继续走循环
					if(si.h<=q.items[j].lh)
					{
						si.lx=q.items[j].x;
						//continue;
					}
					else//如果我高于,那么就要做操作
					{
						//queue队列更新,在j节点之前j-1节点之间插入一个新的节点,si更新继续走循环
						flag=q.insert(j, si.lx, si.h);
						
						if(flag)
							{
								si.lx=q.items[j+1].x;
							}
						else
						{
							si.lx=q.items[j].x;
						}
						//continue;
					}
				}
				if(si.rx-si.lx<0)
				{
					if(flag)
					{
						q.insert(j+1, si.rx, hh);
					}
					else
					{
						q.insert(j, si.rx, hh);
					}
					break;
				}
				//如果没有交集,,就是比你小
				if(si.rx-si.lx==0)
				{
					//如果长度等于0,跳出来即可
					break;
				}
			}
		}
		
		
		q.clear();
		for(int i1=0;i1<20;i1++)
		{
			System.out.println(""+i1+"# x:"+q.items[i1].x+" rh:"+q.items[i1].rh);
		}
	}

}

Divide and Conquer

//南京农业大学  网工152  15115325 高翔

Given n rectangular buildings in a 2-dimensional city, computes the skyline of these buildings, eliminating hidden lines. The main task is to view buildings from a side and remove all sections that are not visible.

All buildings share common bottom and every building is represented by triplet (left, ht, right)
‘left’: is x coordinated of left side (or wall).‘right’: is x coordinate of right side‘ht’: is height of building.
A skyline is a collection of rectangular strips. A rectangular strip is represented as a pair (left, ht) where left is x coordinate of left side of strip and ht is height of strip.

Input: Array of buildings
       { (1,11,5), (2,6,7), (3,13,9), (12,7,16), (14,3,25),
         (19,18,22), (23,13,29), (24,4,28) }
Output: Skyline (an array of rectangular strips)
        A strip has x coordinate of left side and height 
        (1, 11), (3, 13), (9, 0), (12, 7), (16, 3), (19, 18),  

        (22, 3), (25, 0)

1.建立两个链表,一个是存储源元素,三维的那个,一个存储目标元素,二维的那个,三维链表不妨叫做SQueue,二位目标的那个链表不妨叫做Queue;

2.SQueue之中的元素构成为(lx,h,rx) Queue之中的元素构成为(lh,x,rh)----->可以简化为(x,rh)但是目前lh的作用似有似无,可以肯定的是作用很小;

3.目标链表之中预先存放进去两个初始元素(0,1,0),(0,100,0)代表一个很长的(100只是表示一个达不到的长度,当然可以设置的很大),初始的,但是没有高度的建筑,接下来的所有的操作都是建立在切分这个建筑的基础之上;

4,第一个循环遍历SQueue,读取这个链表之中的元素,取出名字叫做si

5,第二层循环,遍历链表queue,逐个比较元素

6,如si.lx会小于该元素的x值,停下来比较高度

7,切分建筑,以x切一刀,左边的归并,右边的剩下来继续遍历下一组(具体的细节处理,看源码看注释)

-----------------------------

思维导图:




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值