UVA 132 Bumpy Objects【凸包变形】【附图】

题目大意:抛过题意,直接抽取模型。

                     平稳边:

                     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;
}


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