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 input consists of several test cases.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.
輸出
For each case, print your answer with the following format:?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 33 1 1 2 2 1 14 1 1 2 2 3 3 2 20示例輸出
C CC Remove 1 bead(s), C提示
來源
2010年山東省第一屆ACM大學生程序設計競賽計算幾何 + DP。 題意是給你n個點,第i個點和第i+1個點可以構成向量,問最少刪除多少個點可以讓構成的向量順時針旋轉或者逆時針旋轉。 思路: 計算幾何用的知識是求叉積和點積,這道題可以加深理解這兩個計算幾何基礎知識點的用法。叉積的作用是判斷兩個向量的左右(順逆),點積的作用是判斷兩個向量的前后。舉個例子,假設有2個向量v1,v2,‘*’暫時代表叉積運算,‘·’暫時代表點積運算。叉積判定:如果v1*v2>0,則v1在v2的順時針方向;如果v1*v2=0,則v1、v2共線;如果v1*v2<0,則v1在v2的逆時針方向。點積判定:如果v1·v2>0,則v1和v2都指向同一側面;如果v1·v2=0,則v1和v2垂直;如果v1·v2<0,則v1和v2都指向相反的側面。
DP是用來記錄所有可能情況的最大向量數,dp[j][i]表示以向量ji(第j個點到第i個點構成的向量)為終點的最大順時針/逆時針向量數。狀態轉移方程為 dp[j][i] = max{dp[k][j]+1}。 判斷如果順時針逆時針關系可以用叉積,如果共線再用點積判斷同方向還是反方向。 注意的點: 1、規定順時針的旋轉范圍是(0<=T<180),逆時針的旋轉范圍是(0<T<=180),也就是說如果兩條向量共線的話,順時針旋轉可以同方向(T=0),不能反方向;逆時針旋轉可以反方向(T=180),不能同方向。 2、如果刪掉一定點后,順時針旋轉的最大向量數和逆時針的一樣,則取順時針的值輸出。否則會WA。 參考博客:http://blog.csdn.net/cyendra/article/details/8859274 代碼: 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
轉載于:https://www.cnblogs.com/yym2013/p/3664483.html
總結
以上是生活随笔為你收集整理的sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV2学习笔记(一)
- 下一篇: java 字符串排序