usc week 5 计算几何(包含凸包) 队内练习题
第一题 shape of hdu http://acm.hdu.edu.cn/showproblem.php?pid=2108
这个 看样子 大嘴鸟的我还得优化一下~~为什么别人的代码都是600多b为什么我的写了2600多b呢~~~
算法: 过多边形任意一边做一条直线,如果其他各顶点都在这条直线的同侧,则把这个多边形叫做凸多边形 我采用的是 (1)输入数据 (2)以相邻两点作为直线进行判断存在三种情况(我是利用高中的两点式求直线方程的~~) 1平行x轴直线 2平行y轴直线 3既不平行x轴也不平行y轴 (3)判断除了做这两条直线上的点,其他的点都是否在这条直线上的一边。 判断是否满足条件~~~ 贴上代码~~ #include<stdio.h> struct stu{ float x,y; } point[1000000]; int n,sum1,sum2,sum,flag2,flag1,flag; //flag 是用来判断 特殊情况 平行x轴,y轴。 int judge(void); int judgex(int i); //判断平行x轴情况 int judgey(int i); //判断平行y轴情况 int main() { int i,t,result; while(scanf("%d",&n)&&n!=0){ //输入数据 for(i=1;i<=n;i++) scanf("%f %f",&point[i].x,&point[i].y); point[i].x=point[1].x; point[i].y=point[1].y; sum1=sum2=sum=0; result=judge(); if(result==1)printf("convex\n"); //根据judge的返回值来判断是否是凸包 else printf("concave\n"); } } int judge(void) { int recycle,i,j; float a,b; recycle=n; for(j=1;j<=recycle;j++){ //判断所有点是否在一条直线的同侧 flag1=flag2=flag=0; if(point[j].x-point[j+1].x==0){judgey(j);if(flag==1)sum++;/*printf("sum=%d\n",sum);*/continue; } if(point[j].y-point[j+1].y==0){judgex(j);if(flag==1)sum++;/*printf("sum=%d\n",sum);*/ continue; } a=(point[j].y-point[j+1].y)/(point[j].x-point[j+1].x); b=point[j].y-a*point[j].x; //printf("a=%f b=%f\n",a,b); // sum1=sum2=0; for(i=1;i<=recycle;i++) { if(i==j||i==j+1) { sum1++;sum2++; //printf("sum1=%d sum2=%d\n",sum1,sum2); // continue; } if(a*point[i].x-point[i].y+b>=0) sum1++; if(a*point[i].x-point[i].y+b<=0) sum2++; //printf("sum1=%d sum2=%d\n",sum1,sum2); // } if(sum1==n||sum2==n) sum++; // printf("sum=%d\n",sum); } // printf("sum=%d\n",sum); // if(sum==n)return 1; else return 0; } int judgex(int i) { int j; for(j=1;j<=n;j++) { if(point[i].y>=point[j].y)flag1++; if(point[i].y<=point[j].y)flag2++; } if(flag1==n||flag2==n)flag=1; } int judgey(int i) { int j; for(j=1;j<=n;j++) { if(point[i].x>=point[j].x)flag1++; if(point[i].x<=point[j].x)flag2++; } if(flag1==n||flag2==n)flag=1; }
进行的是对内赛的第二题 http://openoj.awaysoft.com:8080/judge/contest/view.action?cid=173#problem/B
此乃poj上的计算几何问题
要注意的是最后的面积可能超出结果,所以采用longlong形式存储
算法(1)
1 先一次将每次移动的坐标输入进去
2 然后队坐标进行差乘运算
Area of polygon
The area of a polygon with vertices (x 1, y 1), ..., (x n, y n) is equal to the determinant:
1 | x1 x2 ... xn |
--- | |
2 | y1 y2 ... yn |
where the determinate is defined to be similar to the 2 by 2 determinant: x1 y2 + x2y3+ ... + xn y1 - y1 x2 - y2x3 - ... - yn x1
3 得出最后的结果
贴代码:
#include<stdio.h> structnode{ int x,y; }point[1000010]; void map(void); int i; int main() { int n; char num; scanf("%d",&n); // printf("%d\n",n); getchar(); while(n--){ i=0; point[i].x=point[i].y=0; while(scanf("%c",&num)&&num!='5'){ i++; // printf("i=%d\n",i); switch(num){ case '8':point[i].x=point[i-1].x;point[i].y=point[i-1].y+1;break; case '2':point[i].x=point[i-1].x;point[i].y=point[i-1].y-1; break; case '6':point[i].x=point[i-1].x+1; point[i].y=point[i-1].y;break; case '4':point[i].x=point[i-1].x-1; point[i].y=point[i-1].y;break; case '1':point[i].x=point[i-1].x-1; point[i].y=point[i-1].y-1;break; case '3':point[i].x=point[i-1].x+1; point[i].y=point[i-1].y-1;break; case '7':point[i].x=point[i-1].x-1; point[i].y=point[i-1].y+1;break; case '9':point[i].x=point[i-1].x+1; point[i].y=point[i-1].y+1; } // printf("x=%d y=%d\n",point[i].x,point[i].y); } getchar(); point[i].x=point[i].y=0; // printf("x=%d y=%d\n",point[i].x,point[i].y); map(); } } void map(void){ // printf("ii=%d",i); int j=0; long long s=0; if(i==0)printf("0\n"); else { for(j=0;j<=i-1;j++) { s+=long (point[j].x*point[j+1].y-point[j].y*point[j+1].x); // printf("%d\n",s); } if(s<0)s=0-s; if(s%2==1)printf("%I64d.5\n",s/2); else printf("%I64d\n",s/2); } }