[Noip模拟赛] Polygon
POLYGON
源程序名 POLYGON.??? (PAS,C,CPP)
可执行文件名 POLYGON.EXE
输入文件名 POLYGON.IN
输出文件名 POLYGON.OUT
对于一个多边形来说,在该多边形内任取两点,如果这两点连成的线段落在多边形内,则称这样的多边形为凸多边形。
平面上有N个坐标值为自然数的圆点。顶点数最多凸多边形是指由给定的圆点中的一部分组成的凸多边形,它包含最大可能的顶点数。原点,即坐标内中心(0,0)必须是顶点数最多凸多边形的一个顶点。
编写程序求出这样的凸多边形的最大顶点数。注意一个多边形的连续的边不能是平行的。
输入
输入文件的第一行包含一个自然数N,2≤N≤100,表示给定的圆点数。
下面的N行每行包含两个用空格隔开的自然数X和Y,1≤X≤100,1≤Y≤100,表示一个圆点的坐标值。所有的圆点是不相同的。
输出
输出文件的第一行也是唯一的一行应该包含顶点数最多凸多边形的顶点数。注意结果应不小于3。
样例
POLYGON.IN
8
10 8
3 9
2 8
2 3
9 2
9 10
10 3
8 10
POLYGON.OUT
8
【题解】
有点坑。。第一眼看成求凸包顶点数了结果竟然还有50分= =
然后后面想了半天不会做
然后呢想了半天发现设f[i,j]表示最后两个点为i和j的情况下凸多边形最大顶点数
那么枚举k [1...i-1]即可,f[i,j]即可用f[k,i]更新
更新的情况当且仅当是个凸多边形(用向量叉积判断)
1 #include <stdio.h> 2 using namespace std; 3 struct P { 4 int x,y; 5 }p[105]; 6 int n; 7 int f[105][105]; 8 // f i,j 表示凸多边形的最后两个顶点为i,j所构成的最多顶点数 9 inline void IO() { 10 freopen("polygon.in","r",stdin); 11 freopen("polygon.out","w",stdout); 12 } 13 inline int max(int a,int b) {return a<b?b:a;} 14 inline void swap(P &a, P &b) { 15 int _tem; 16 _tem=a.x, a.x=b.x, b.x=_tem; 17 _tem=a.y, a.y=b.y, b.y=_tem; 18 } 19 inline int cj(P a, P b) { 20 return a.x*b.y-b.x*a.y; 21 } 22 23 inline void RS() { 24 p[0].x=0, p[0].y=0; 25 scanf("%d",&n); 26 for (int i=1;i<=n;++i) scanf("%d %d",&p[i].x,&p[i].y); 27 //按照斜率排序 28 for (int i=1;i<n;++i) for (int j=i+1;j<=n;++j) 29 if (p[i].x*p[j].y < p[j].x*p[i].y) // y1/x1 > y2/x2 30 swap(p[i],p[j]); 31 for (int i=1;i<=n;++i) f[0][i]=1; 32 for (int i=1;i<=n;++i) 33 for (int j2=i+1;j2<=n+1;++j2) 34 for (int k=0;k<=i-1;++k) { 35 int j; 36 P _x, _y; int _tem; 37 if (j2==n+1) j=0; 38 else j=j2; 39 _x.x=p[i].x-p[k].x, _x.y=p[i].y-p[k].y; 40 _y.x=p[j].x-p[i].x, _y.y=p[j].y-p[i].y; 41 int c = cj(_y,_x); 42 if (c<0) f[i][j]=max(f[i][j],f[k][i]+1); 43 } 44 int ans=0; 45 for (int i=0;i<=n;++i) 46 for (int j2=i+1;j2<=n+1;++j2) { 47 int j; 48 if (j2==n+1) j=0; else j=j2; 49 ans = max(ans,f[i][j]); 50 } 51 printf("%d\n",ans); 52 } 53 int main() { 54 IO(), 55 RS(); 56 return 0; 57 }
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net