題目大意:拋過題意,直接抽取模型。
平穩邊:
1,多邊形上兩頂點之間的邊,與多邊形非規範相交(通俗點就是線段沿着凸包的輪廓走!)。
2,通過旋轉多邊形使該邊水平,並且多邊形重心在其上方,重心在線段兩端點之間。
題目要求:多邊形頂點逆時針給出,給每條平穩線段編號(取線段頂點最大值),求出編號最小的平穩邊的編號。
解題策略:求出多邊形凸包,逆時針枚舉凸包每一條邊;
重心在不在其上方——>叉積計算螺旋方向判斷
重心在不在線段兩端點之間——>根據點積判斷,我寫了下流程判斷,大家可以參考下:
這道題又是1A,感覺最近有進步!加油!
/*
UVA 132 Bumpy Objects
AC by J_Dark
ON 2013/5/8 9:25
Time 0.012s
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <climits>
#include <algorithm>
#include <vector>
using namespace std;
/////////////////////////////////////
struct point{
double x, y;
int iniPos;
point(double a=0, double b=0, int c=-1){
x = a;
y = b;
iniPos = c; //記錄凸包頂點在原多邊形位置
}
void set(double a, double b){
x = a;
y = b;
}
double Distance(point t){
return sqrt((x-t.x)*(x-t.x) + (y-t.y)*(y-t.y));
}
};
vector<point> p;
vector<int> CH; //存放凸包頂點序號 模擬棧
int top, nodeNum;
point MC; //重心
string polyName;
/////////////////////////////////////
void Input(){
p.clear();
CH.clear();
double xx, yy;
cin >> xx >> yy;
MC.set(xx,yy); //重心
nodeNum = 0;
while(cin >> xx >> yy && (xx || yy))
{
p.push_back(point(xx, yy, ++nodeNum));
//nodeNum++;
}
CH.resize(nodeNum+5);
}
//計算凸包
bool cmp(point a, point b){
if(a.y == b.y) return a.x < b.x;
return a.y < b.y;
}
bool turnRight(point px1, point px2, point pp){
const double eps = 1e-20;
if((px2.x - px1.x)*(pp.y - px2.y) - (pp.x - px2.x)*(px2.y - px1.y) <= eps) return true;
return false;
}
void ComputeCH(){
sort(p.begin(), p.end(), cmp);
CH[0] = 0;
CH[1] = 1;
top = 1;
//從起點0到到排序最後點作凸包右鏈 過程1
for(int i=2; i<nodeNum; i++){
while( top && turnRight(p[CH[top-1]], p[CH[top]], p[i]) )
{
top--;
}
CH[++top] = i;
}
int len = top;
//從排序最高點到到起點0fab反向作凸包右鏈 過程2
CH[++top] = nodeNum-2;
for(int i=nodeNum-3; i>=0; i--){
//top!=len, 不考慮已在過程1生成凸包上的點
while( top!=len && turnRight(p[CH[top-1]], p[CH[top]], p[i]) )
{
top--;
}
CH[++top] = i;
}
}
//計算p2-p1-pp三邊夾角cos大小正負
bool between(point p1, point p2, point pp){
if( ((pp.x-p1.x)*(p2.x-p1.x)+(pp.y-p1.y)*(p2.y-p1.y)) / fabs(pp.Distance(p1)* p2.Distance(p1)) > 0)
return true;
return false;
}
void findAns(){
int ans = INT_MAX;
//cout << "nodeNum : " << nodeNum << endl;
for(int i=0; i<top; i++){
//若重心在凸包當前邊左側且重心在當前邊兩端點之間
if(!turnRight(p[CH[i]], p[CH[(i+1)%top]], MC)
&& between(p[CH[i]], p[CH[(i+1)%top]], MC)
&& between(p[CH[(i+1)%top]], p[CH[i]], MC)){
ans = min(ans, max(p[CH[i]].iniPos, p[CH[(i+1)%top]].iniPos));
//printf("ans = %d %d %d\n", ans, p[CH[i]].iniPos, p[CH[(i+1)%top]].iniPos);
}
}
//經驗證,一個空格足矣
cout << polyName << " " << ans << endl;
}
///////////////////////////////////////////////////////
int main(){
while(cin >> polyName && polyName[0]!='#')
{
Input();
ComputeCH(); //計算凸包
findAns(); //找到編號基邊最大最小值
}
return 0;
}