題目描述:
給定一些點,輸出最大面積的凸邊形。輸出起始點爲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;
}
如果有錯誤,還請高手指正。