2016華爲機試題目:最大的凸多邊形

題目描述:

給定一些點,輸出最大面積的凸邊形。輸出起始點爲x軸最左邊的點,按照順時針方向輸出,每個點必須是凸邊形的頂點(不輸出邊上或凸邊形內的點)。

輸入樣例: 
3;1,2;2,2;3,3 
輸出樣例: 
1,2;3,3;2,2

注: 
- 輸入數據的第一個數爲點的數目,然後是分號;再後面就是以分號間隔的點; 
- 點的數目最少爲3個,最多爲65535; 
- 該題目和斜率相關。

個人認爲,本題主要的難點在於邊上的兩個點傾斜角是90度的時候,這種特殊情況需要考慮,一般情況下直接根據斜率就可以找到了。

我通過從最左邊的點A(如果和A垂直的有點,從最上方的點)開始,找其右邊斜率最大的點,把該點加入,直到遇到最右邊最下邊的點B,或者到某點的時候,大於其橫座標的點不存在,那也停止查找。然後從B點往回找,找其座標與其斜率最大的點,直到找到A或找到某一點其左邊沒點爲止。下面是具體的程序代碼

#include <iostream>
using namespace std;
int main(){
	int N;
	cin>>N;
	int **pt=new int*[N];
	for(int i=0;i<N;i++)
		pt[i]=new int[2];
	for(int i=0;i<N;i++){
		int tN1,tN2;
		cin>>tN1>>tN2;
		pt[i][0]=tN1;
		pt[i][1]=tN2;
	}
	int min=pt[0][0];
	int pmin=0;//取最左邊的最上邊的數
	for(int i=1;i<N;i++){
		if(pt[i][0]<min){
			min=pt[i][0];
			pmin=i;
		}else if(pt[i][0]==min){
			if(pt[i][1]>pt[pmin][1])
				pmin=i;
		}
	}
	int max=pt[0][0];
	int pmax=0;//取最右邊的最下邊的數
	for(int i=1;i<N;i++){
		if(pt[i][0]>max){
			max=pt[i][0];
			pmax=i;
		}else if(pt[i][0]==max){
			if(pt[i][1]<pt[pmax][1])
				pmax=i;
		}
	}
	int result[65535];//用來存放凸多邊形座標的下標
	int s=0;
	int tmpmin=pmin;
	while(tmpmin!=pmax){
		result[s++]=tmpmin;
		int temp=tmpmin;
		double tmpangle;
		for(int i=0;i<N;i++){//爲了取一條斜率值給tmpangle賦初值,初值可以是最小數,也可以是任一斜率
			if(pt[i][0]>pt[tmpmin][0]){
				tmpangle=(double)((pt[i][1]-pt[tmpmin][1])/(pt[i][0]-pt[tmpmin][0])-1);
				break;
			}
		}
		for(int i=0;i<N;i++){
			if(i==tmpmin) continue;
			double ttt;
			if(pt[i][0]>pt[tmpmin][0]){
				ttt=(double)(pt[i][1]-pt[tmpmin][1])/(pt[i][0]-pt[tmpmin][0]);
				if(ttt>tmpangle){
					tmpangle=ttt;
					temp=i;
				}
			}
		}
		if(temp==tmpmin){//如果其右邊沒有數字,則終止循環,這是考慮最右邊豎着有好幾個點的情況
			tmpmin=pmax;
		}else{
			tmpmin=temp;
		}
	}
	int tmpmax=tmpmin;
	while(tmpmax!=pmin){
		result[s++]=tmpmax;
		int temp=tmpmax;
		double tmpangle;
		for(int i=0;i<N;i++){//爲了取一條斜率值給tmpangle賦初值,初值可以是最小數,也可以是任一斜率
			if(pt[i][0]<pt[tmpmax][0]){
				tmpangle=(double)((pt[i][1]-pt[tmpmax][1])/(pt[i][0]-pt[tmpmax][0])-1);
				break;
			}
		}
		for(int i=0;i<N;i++){
			if(i==tmpmax) continue;
			if((pt[i][0]<pt[tmpmax][0]) && (double)(pt[i][1]-pt[tmpmax][1])/(pt[i][0]-pt[tmpmax][0])>tmpangle){
				tmpangle=(double)(pt[i][1]-pt[tmpmax][1])/(pt[i][0]-pt[tmpmax][0]);
				temp=i;
			}
		}
		if(temp==tmpmax){
			tmpmax=pmin;
		}else{
			tmpmax=temp;
		}
	}
	for(int i=0;i<s;i++){
		cout<<pt[result[i]][0]<<" "<<pt[result[i]][1]<<endl;
	}
	for(int i=0;i<N;i++)
		delete pt[i];
	delete[] pt;
	return 0;
}


如果有錯誤,還請高手指正。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章