题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2153
Clockwise 只要理解题目意思,即可敲出正确代码。
题目大意为:给你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;
}
|