http://acm.hdu.edu.cn/showproblem.php?pid=3952
这道题目是Alibaba程序设计公开赛的一道题目,以前没怎么做过计算几何的题目,也没有整理过模板,所以那天比赛的时候我就悲剧了~
今天想到了,所以整理一下,也顺便把直线与线段相交的模板整理出来。
题意很好理解,就是给你一些互不相交的多边形,让你用一条直线去穿这些多边形,问最多能穿过多少,而且如果这条直线只穿过多边形的一个顶点,也认为是穿过了这个多边
形。
数据量不是很大,枚举完全可以过掉,思路就是选择任意的两个多边形上面的任意两个顶点,然后判断这两个顶点最多能通过多少个多边形,然后取最大值就可以了。
代码如下:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int k;
int x[12],y[12];
}point[12];
//利用叉乘判断两直线是否相交,如果相交返回true,否则返回false
bool judge(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
int a,b,c,d,e,f;
a=x3-x1,b=y3-y1;
c=x2-x1,d=y2-y1;
e=x4-x1,f=y4-y1;
if((a*d-b*c)*(c*f-d*e)>=0) return true;
return false;
}
int main()
{
int t,n;
scanf("%d",&t);
for(int Case=1;Case<=t;Case++)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&point[i].k);
for(int j=0;j<point[i].k;j++)
scanf("%d%d",&point[i].x[j],&point[i].y[j]);
}
if(n==1)
{
printf("Case %d: 1\n",Case);continue;
}
int ans;
int max=0;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
for(int k=0;k<point[i].k;k++)
{
for(int p=0;p<point[j].k;p++)
{
ans=2;
for(int q=0;q<n;q++)
{
if(q==i||q==j) continue;
for(int s=0;s<point[q].k-1;s++)
{
if(judge(point[i].x[k],point[i].y[k],point[j].x[p],point[j].y[p],point[q].x[s],point[q].y[s],point[q].x[s+1],point[q].y[s+1]))
{
ans++;
break;
}
}
}
if(max<ans) max=ans;
}
}
}
}
printf("Case %d: %d\n",Case,max);
}
return 0;
}