題意:我是真的沒看懂題意qaq。。。搜了才知道。題目給了n個點,問這n個點確定的凸包是否能通過新增點來變成乙個新的凸包。也就是這個凸包是否穩定,穩定輸出yes,否則輸出no。
思路:首先給出結論,乙個凸包穩定當且僅當它的每一條邊上都有》=3個點。因為如果只有兩個點的話,那麼在這條邊之外取乙個點就能擴充套件出乙個更大的凸包。而每條邊上都有》=3個點時,此時擴充套件時會使得凸包變凹!
所以我們需要改一下求凸包的模板,只用將while中的<=改成< 即可,但這不能將最後一條邊上的多個點保留 ,因為排序時將距離近的點排在前面 ,那麼最後一條邊上的點僅有距離最遠的會被保留,其餘的會被出棧。所以最後一條邊需要特判。(網上許多**沒有特判,僅僅只是在判斷的時候忽略了最後一條邊,然而資料弱,沒有卡這個點,所以能ac)。
求凸包之後需要判斷每條邊是不是由》=3個點。可以利用叉積判斷點i處和點(i+1)處的夾角是否都不為0來判斷,如果都不為0那麼邊(i , i+1)就不滿足條件,因為前面特判了最後一條邊(top , 0),所以這裡列舉判斷時就不用列舉最後一條邊了。
ac code:
#include#include#include
#include
using
namespace
std;
const
int maxn=1005
;const
double pi=acos(-1.0
);struct
point
point(
int x,int
y):x(x),y(y){}
}list[maxn];
intstack[maxn],top,flag;
//計算叉積p0p1×p0p2
intcross(point p0,point p1,point p2)
//計算p1p2的距離
double
dis(point p1,point p2)
//極角排序函式,角度相同則距離小的在前面
bool
cmp(point p1,point p2)
//輸入,把最左下角放在list[0],並且進行極角排序
void init(int
n) }
list[k]=list[0
]; list[
0]=p0;
sort(list+1,list+n,cmp);}//
graham掃瞄法求凸包,凸包頂點存在stack棧中
//從棧底到棧頂一次是逆時針方向排列的
void graham(int
n) top=1
; stack[
0]=0
; stack[
1]=1
;
for(int i=2;ii)
if(cross(list[n-2],list[n-1],list[0])!=0) //
特判最後一條邊
flag=0;}
bool
check()
return
true;}
intt,n;
intmain()
graham(n);
if(!flag)
if(check()) printf("
yes\n");
else printf("
no\n");
}return0;
}
Poj1228 穩定凸包
題意 給定一些點,問這些點能不能夠成穩定的凸包,這有點不明不白的,我也是看了別人的報告才搞明白題意的,就是如果凸包上的一條邊如果不包含三個以上的點,它就是可以被向外擴充套件的.解題 弄明白了題意,以為會很簡單了,直接掃瞄求凸包就行了,而且是不用退棧的過程,後來在實現過程中才發現,即使給出的所有點都在...
POJ1228 穩定凸包
看題半天沒看懂意思,以為就是判斷是否有凸包結果。看了題解才知道,是要確定乙個凸包是否唯一,即不能通過新增點變成新的凸包,也就是凸包的每條邊上至少有3個點。include include include include include define maxl 1010 define eps 1e 8 ...
POJ 1228 穩定凸包
解題思路 所謂穩定凸包就是不存在凸包外加入乙個點使得形成的新凸包還包含原凸包的所有點。所以要使他是穩定的,那麼凸包的每條邊都必須有三個點,也就是除了兩個端點外邊上還有一點,這樣如果要在外加入乙個點的話必然使得邊上的點被消除,所以這樣的凸包也就是穩定的了。include include include...