题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2153
题目大意为:给你n个点,让你求出任意一个向量,顺时针旋转180(不能到达180),如果可以达到其余n-2个点,就输出‘C’,逆时针旋转180,如果可以到达n-2个点,就输出‘CC’,如果都不能,看顺时针到达的点数多,还是逆时针达到的点数多,舍弃点数少的一侧。如果两边相等,算作顺时针方向。
用叉乘判断是顺时针方向还是逆时针方向,如果共线,则再利用点乘判断是否符合条件。用dp数组保存最大数。代码如下:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define eps 1e-9 using namespace std; struct point { double x,y; point(double x=0,double y=0):x(x),y(y) {} }; point p[310]; int dp[310][310]; typedef point Vector; Vector operator - (point a,point b) { return Vector(a.x-b.x,a.y-b.y); } double cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; } double dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } bool check1(int i,int j,int k) { Vector v1=p[i]-p[j]; Vector v2=p[j]-p[k]; double x=cross(v1,v2); if(x-eps>0) return true; else if(x+eps<0) return false; else { double d=dot(v1,v2); if(d+eps<0) return false; else return true; } } bool check2(int i,int j,int k) { Vector v1=p[i]-p[j]; Vector v2=p[j]-p[k]; int x=cross(v1,v2); if(x-eps>0) return false; else if(x+eps<0) return true; else { int d=dot(v1,v2); if(d+eps<0) return true; return false; } } int main() { int n; while(scanf("%d",&n),n) { int i,j,k; for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); int r1=0,r2=0; memset(dp,0,sizeof(dp)); for(i=0;i<n;i++) for(j=0;j<i;j++) { dp[j][i]=1; for(k=0;k<j;k++) if(check1(i,j,k)) dp[j][i]=max(dp[j][i],dp[k][j]+1); r1=max(r1,dp[j][i]); } memset(dp,0,sizeof(dp)); for(i=0;i<n;i++) for(j=0;j<i;j++) { dp[j][i]=1; for(k=0;k<j;k++) if(check2(i,j,k)) dp[j][i]=max(dp[j][i],dp[k][j]+1); r2=max(r2,dp[j][i]); } if(r1==n-1) printf("C\n"); else if(r2==n-1) printf("CC\n"); else if(r1>=r2) printf("Remove %d bead(s), C\n",n-1-r1); else printf("Remove %d bead(s), CC\n",n-1-r2); printf("\n"); } return 0; }