1. 程式人生 > >凸包問題(列舉)

凸包問題(列舉)

凸包的定義,直觀的來看就是,由平面上n個點組成的集合,其凸包就是包含這些點的最小凸多邊形,凸多邊形的任何一條邊所在的直線把凸多邊形全部劃在了同一個半平面內。

性質:如果點集中兩個點的連線屬於凸多邊形的邊,當且僅當點集中其餘的點都在這兩個點連線的同一側。利用這個性質,可以求解凸包問題。若已知由n個點構成集合的凸包是以其中某些點為頂點的凸多邊形(這個凸多邊形一定是最小凸多邊形),且這些點具有凸包的性質,則它們之間的某些連線共同構成了凸包的全部邊。

解題思路:利用數學中兩點確定一條直線的方程列舉求解。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

struct Point
{
	int x,y,flag;
}; 

struct Point point[100];

void random(int n)
{
	srand(time(NULL));
	for(int i=0;i<n;i++)
	{
		point[i].x=1+rand()%10;
		point[i].y=1+rand()%10;
	}
} 

void ConvexHull(int n)
{
	int sum=0;
	int sign1,sign2;
	int a,b,c;
	for(int i=0;i<n;i++)
		for(int j=i+1;j<n;j++)
		{
			a=
			point[j].y-point[i].y;
			b=point[j].x-point[i].x;
			c=(point[i].x*point[j].y)-(point[i].y*point[j].x);
			sign1=0;
			sign2=0;
			for(int k=0;k<n;k++)
			{
				if((k==j)||(k==i))continue;
				if((a*point[k].x-b*point[k].y)==c)
				{
					++sign1;
					++sign2;
				}
				if((a*point[k].x-b*point[k].y)>c)
					++sign1;
				if((a*point[k].x-b*point[k].y)<c)
					++sign2;
			}
			if(sign1==(n-2)||sign2==(n-2))
			{
				point[i].flag=1;
				point[j].flag=1;
			}
		}
	printf("\n凸包的極點座標為:\n");
	for(int i=0;i<n;i++)
		if(point[i].flag==1)
		{	sum++;
			printf("(%d,%d)\n",point[i].x,point[i].y);
		}
	printf("\n一共有%d個點為極點.\n",sum);
}

int main()
{
	int n;
	printf("請輸入座標個數n:\n");
	scanf("%d",&n);
	random(n);
	printf("\n平面的%d個座標為:\n",n);
	for(int i=0;i<n;i++)
	{	
		printf("(%d,%d)\n",point[i].x,point[i].y);
	}
	ConvexHull(n);
	return 0;
}