sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)
Clockwise
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
Saya have a long necklace with N beads, and she signs the beads from 1 to N. Then she fixes them to the wall to show N-1 vectors – vector i starts from bead i and end up with bead i+1.
One day, Kudo comes to Saya’s home, and she sees the beads on the wall. Kudo says it is not beautiful, and let Saya make it better.
She says: “I think it will be better if it is clockwise rotation. It means that to any vector i (i < N-1), it will have the same direction with vector i+1 after clockwise rotate T degrees, while 0≤T<180.”
It is hard for Saya to reset the beads’ places, so she can only remove some beads. To saving the beads, although she agrees with Kudo’s suggestion, she thinks counterclockwise rotation is also acceptable. A counterclockwise rotation means to any vector i (i < N-1), it will have the same direction with vector i+1 after counterclockwise rotate T degrees, while 0 < T ≤ 180.”
Saya starts to compute at least how many beads she should remove to make a clockwise rotation or a counterclockwise rotation.
Since the necklace is very-very long, can you help her to solve this problem?
输入
The first line of input in each test case contains one integer N (2<N≤300), which represents the number of beads.
Each of the next N lines contains two integer x and y, represents the coordinate of the beads. You can assume that 0<x,y<10000.
The last case is followed by a line containing one zero.
输出
If it is clockwise rotation without removing any beads, please print “C; otherwise if it is counterclockwise rotation without removing any beads, print “CC” instead; otherwise, suppose remove at least x beads to make a clockwise rotation and remove at least y beads to make a counterclockwise rotation. If x≤y, print “Remove x bead(s), C”, otherwise print “Removey bead(s), CC” instead.
Your output format should imitate the sample output. Print a blank line after each test case.
示例输入
3 1 1 2 2 3 3 3 1 1 2 2 1 1 4 1 1 2 2 3 3 2 2 0
示例输出
C CC Remove 1 bead(s), C
提示
来源
1 #include <iostream>
2 #include <cmath>
3 #include <string.h>
4 using namespace std;
5 #define eps 1e-10
6 int dp[310][310];
7 /********** 定义点 **********/
8 struct Point{
9 double x,y;
10 Point(double x=0,double y=0):x(x),y(y) {}
11 };
12 Point p[310];
13 /********** 定义向量 **********/
14 typedef Point Vector;
15 /********** 点 - 点 = 向量 **********/
16 Vector operator - (Point a,Point b)
17 {
18 return Vector(a.x-b.x,a.y-b.y);
19 }
20 /********** 2向量求叉积 **********/
21 double Cross(Vector a,Vector b)
22 {
23 return a.x*b.y-b.x*a.y;
24 }
25 /********** 向量点积 **********/
26 double Dot(Vector a,Vector b)
27 {
28 return a.x*b.x+a.y*b.y;
29 }
30 bool check1(int i,int j,int k) //核对向量ji是否在向量kj的顺时针方向或者同方向
31 {
32 if(k==0) return true;
33 Vector v1 = p[i]-p[j]; //向量ji
34 Vector v2 = p[j]-p[k]; //向量kj
35 double x = Cross(v1,v2);
36 if(fabs(x)<eps){ //向量ji和kj共线,判断一下两向量方向。
37 double d = Dot(v1,v2);
38 if(d>eps) //顺时针可以有同方向(0≤T<180)
39 return true;
40 else //反方向
41 return false;
42 }
43 else if(x>eps){ //向量ji在向量kj的顺时针方向
44 return true;
45 }
46 return false;
47 }
48 bool check2(int i,int j,int k)
49 {
50 if(k==0) return true;
51 Vector v1 = p[i]-p[j]; //向量ji
52 Vector v2 = p[j]-p[k]; //向量kj
53 double x = Cross(v1,v2);
54 if(fabs(x)<eps){ //向量ji和kj共线,判断一下两向量方向
55 double d = Dot(v1,v2);
56 if(d>eps) //同方向
57 return false;
58 else //逆时针可以有反方向(0 < T ≤ 180)
59 return true;
60 }
61 else if(x<eps){ //向量ji在向量kj的逆时针方向
62 return true;
63 }
64 return false;
65 }
66 int main()
67 {
68 int n;
69 while(cin>>n){
70 if(n==0) break;
71 //dp[j][i]表示以向量ji(第j个点到第i个点构成的向量)为终点的最大顺时针向量数
72 int i,j,k;
73 for(i=1;i<=n;i++) //输入n个点
74 cin>>p[i].x>>p[i].y;
75 int r1=0,r2=0; //最大向量数
76 //dp
77 memset(dp,0,sizeof(dp));
78 for(i=2;j<=n;i++)
79 for(j=1;j<i;j++){
80 int Max = 0;
81 for(k=0;k<i;k++){
82 if(check1(i,j,k)){
83 if(dp[k][j]+1>Max)
84 Max = dp[k][j]+1;
85 }
86 }
87 dp[j][i]=Max;
88 if(dp[j][i]>r1)
89 r1 = dp[j][i];
90 }
91 memset(dp,0,sizeof(dp));
92 for(i=2;j<=n;i++)
93 for(j=1;j<i;j++){
94 int Max = 0;
95 for(k=0;k<i;k++){
96 if(check2(i,j,k)){
97 if(dp[k][j]+1>Max)
98 Max = dp[k][j]+1;
99 }
100 }
101 dp[j][i]=Max;
102 if(dp[j][i]>r2)
103 r2 = dp[j][i];
104 }
105 if(r1==n-1) //向量数比点数少一个
106 cout<<"C"<<endl;
107 else if(r2==n-1)
108 cout<<"CC"<<endl;
109 else if(r1>=r2)
110 cout<<"Remove "<<n-1-r1<<" bead(s), C"<<endl;
111 else
112 cout<<"Remove "<<n-1-r2<<" bead(s), CC"<<endl;
113 cout<<endl;
114 }
115 return 0;
116 }
Freecode : www.cnblogs.com/yym2013