sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)
Clockwise
Time Limit: 1000ms?? Memory limit: 65536K??有疑問?點(diǎn)這里^_^
題目描述
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大學(xué)生程序設(shè)計(jì)競賽計(jì)算幾何 + DP。 題意是給你n個(gè)點(diǎn),第i個(gè)點(diǎn)和第i+1個(gè)點(diǎn)可以構(gòu)成向量,問最少刪除多少個(gè)點(diǎn)可以讓構(gòu)成的向量順時(shí)針旋轉(zhuǎn)或者逆時(shí)針旋轉(zhuǎn)。 思路: 計(jì)算幾何用的知識(shí)是求叉積和點(diǎn)積,這道題可以加深理解這兩個(gè)計(jì)算幾何基礎(chǔ)知識(shí)點(diǎn)的用法。叉積的作用是判斷兩個(gè)向量的左右(順逆),點(diǎn)積的作用是判斷兩個(gè)向量的前后。舉個(gè)例子,假設(shè)有2個(gè)向量v1,v2,‘*’暫時(shí)代表叉積運(yùn)算,‘·’暫時(shí)代表點(diǎn)積運(yùn)算。叉積判定:如果v1*v2>0,則v1在v2的順時(shí)針方向;如果v1*v2=0,則v1、v2共線;如果v1*v2<0,則v1在v2的逆時(shí)針方向。點(diǎn)積判定:如果v1·v2>0,則v1和v2都指向同一側(cè)面;如果v1·v2=0,則v1和v2垂直;如果v1·v2<0,則v1和v2都指向相反的側(cè)面。
DP是用來記錄所有可能情況的最大向量數(shù),dp[j][i]表示以向量ji(第j個(gè)點(diǎn)到第i個(gè)點(diǎn)構(gòu)成的向量)為終點(diǎn)的最大順時(shí)針/逆時(shí)針向量數(shù)。狀態(tài)轉(zhuǎn)移方程為 dp[j][i] = max{dp[k][j]+1}。 判斷如果順時(shí)針逆時(shí)針關(guān)系可以用叉積,如果共線再用點(diǎn)積判斷同方向還是反方向。 注意的點(diǎn): 1、規(guī)定順時(shí)針的旋轉(zhuǎn)范圍是(0<=T<180),逆時(shí)針的旋轉(zhuǎn)范圍是(0<T<=180),也就是說如果兩條向量共線的話,順時(shí)針旋轉(zhuǎn)可以同方向(T=0),不能反方向;逆時(shí)針旋轉(zhuǎn)可以反方向(T=180),不能同方向。 2、如果刪掉一定點(diǎn)后,順時(shí)針旋轉(zhuǎn)的最大向量數(shù)和逆時(shí)針的一樣,則取順時(shí)針的值輸出。否則會(huì)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 /********** 定義點(diǎn) **********/ 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 /********** 點(diǎn) - 點(diǎn) = 向量 **********/ 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 /********** 向量點(diǎn)積 **********/ 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) //核對(duì)向量ji是否在向量kj的順時(shí)針方向或者同方向 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) //順時(shí)針可以有同方向(0≤T<180) 39 return true; 40 else //反方向 41 return false; 42 } 43 else if(x>eps){ //向量ji在向量kj的順時(shí)針方向 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 //逆時(shí)針可以有反方向(0 < T ≤ 180) 59 return true; 60 } 61 else if(x<eps){ //向量ji在向量kj的逆時(shí)針方向 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個(gè)點(diǎn)到第i個(gè)點(diǎn)構(gòu)成的向量)為終點(diǎn)的最大順時(shí)針向量數(shù) 72 int i,j,k; 73 for(i=1;i<=n;i++) //輸入n個(gè)點(diǎn) 74 cin>>p[i].x>>p[i].y; 75 int r1=0,r2=0; //最大向量數(shù) 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) //向量數(shù)比點(diǎn)數(shù)少一個(gè) 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
轉(zhuǎn)載于:https://www.cnblogs.com/yym2013/p/3664483.html
總結(jié)
以上是生活随笔為你收集整理的sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV2学习笔记(一)
- 下一篇: java 字符串排序