计算几何
点,线:
poj 1066
题意:给一个矩形,n条在内部线,每次只能通过线段的中点,求从起点走到矩形外要经过几次线段;
显然当我们确定终点后,那些横跨在起点和终点之间的直线是我们无法避免要通过的,且每条直线我们只需要通过一次就好了。
这样我们只要枚举终点,然后判断交点个数就好了。问题的转化,线段平移,或者极端状况。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cmath> 5 #include<queue> 6 #include<cstdlib> 7 #include<vector> 8 #include<algorithm> 9 #include<set> 10 #define pbk push_back 11 using namespace std; 12 const int N=5000+10; 13 const double eps=1e-10; 14 inline int dcmp(double x){ 15 return x<-eps?-1:x>eps; 16 } 17 inline double sqr(double x){ 18 return x*x; 19 } 20 struct Point{ 21 double x,y; 22 Point (double x=0,double y=0):x(x),y(y){} 23 Point operator - (const Point &p)const{ 24 return Point(x-p.x, y-p.y ); 25 } 26 Point operator + (const Point &p)const{ 27 return Point(x+p.x, y+p.y); 28 } 29 Point operator * (const double &k)const{ 30 return Point(x*k, y*k); 31 } 32 Point operator / (const double &k)const{ 33 return Point(x/k, y/k); 34 } 35 double operator * (const Point &p)const{ 36 return x*p.y - y*p.x; 37 } 38 double operator ^ (const Point &p)const{ 39 return x*p.x + y*p.y; 40 } 41 bool operator == (const Point &p)const{ 42 return dcmp(x-p.x)==0 && dcmp(y-p.y)==0; 43 } 44 bool operator < (const Point &p)const{ 45 return dcmp(x-p.x)<0 || (dcmp(x-p.x)==0 && dcmp(y-p.y)<0 ); 46 } 47 double Distance(Point p){ 48 return sqrt(sqr(x-p.x) + sqr(y-p.y)); 49 } 50 void input(){ 51 scanf("%lf%lf",&x,&y); 52 } 53 void ot(){ 54 printf("%lf %lf\n",x,y); 55 } 56 }; 57 struct Line{ 58 Point a,b; 59 Line(){} 60 Line(const Point &_a,const Point &_b):a(_a),b(_b){} 61 double operator * (const Point &p)const{ 62 return (b-a) * (p-a); 63 } 64 double operator ^ (const Point &p)const{ 65 return (p-a) ^ (p-b); 66 } 67 void input(){ 68 a.input(); b.input(); 69 } 70 void ot(){ 71 a.ot(); b.ot(); 72 } 73 bool IsPointInLine(const Point &p){ 74 return !dcmp((*this) * p); 75 } 76 bool IsPointInSeg(const Point &p){ 77 return dcmp((*this) *p) == 0 && dcmp( (*this) ^ p ) <= 0; 78 } 79 bool parallel(Line v){ 80 return !dcmp( (b-a)*(v.b-v.a) ); 81 } 82 int LineCrossSeg(const Line &v){ 83 int d1 = dcmp((*this) * v.a), d2 = dcmp((*this) * v.b); 84 if ( (d1 ^ d2) == -2) return 2; // (-1)^(1) == -2; 85 return (d1 ==0 || d2 == 0); 86 } 87 int LineCrossLine(const Line &v){ 88 if ( (*this).parallel(v) ){ 89 return dcmp(v*a) == 0; 90 } 91 return 2; 92 } 93 Point CrossPoint(const Line &v){ 94 double s1 = v*a, s2 = v*b; 95 return ( a*s2 - b*s1 ) / (s2 - s1); 96 } 97 int SegCrossSeg(const Line &v){ 98 int d1 = dcmp( (*this) * v.a); 99 int d2 = dcmp( (*this) * v.b); 100 int d3 = dcmp(v * a); 101 int d4 = dcmp(v * b); 102 if ( (d1 ^ d2) == -2 && (d3 ^ d4) == -2) return 2;// 2 内部相交 103 return ( (d1 == 0 && dcmp((*this) ^ v.a) <= 0) // 1 端点相交 0 无交点 104 || (d2 == 0 && dcmp((*this) ^ v.b) <= 0) 105 || (d3 == 0 && dcmp(v ^ a) <= 0) 106 || (d4 == 0 && dcmp(v ^ b) <= 0) ); 107 } 108 }; 109 int n; 110 Line L[31]; 111 vector<Point >p; 112 Point st; 113 void solve(){ 114 int ans = -1; 115 for (int i=0;i<p.size();i++){ 116 Line t = Line(st,p[i]); 117 int cnt = 0; 118 for (int j=0;j<n;j++){ 119 if (L[j].SegCrossSeg(t) == 2) cnt++; 120 } 121 if (cnt<ans || ans==-1) ans=cnt; 122 } 123 printf("%d\n",ans+1); 124 } 125 int main(){ 126 while (~scanf("%d",&n)){ 127 printf("Number of doors = "); 128 129 p.clear(); 130 for (int i=0; i<n; i++){ 131 L[i].input(); 132 p.pbk(L[i].a); p.pbk(L[i].b); 133 } 134 st.input(); 135 if (n<=2){ 136 printf("1\n"); continue; 137 } 138 solve(); 139 } 140 141 return 0; 142 }
poj3347
题意:给n个边长为leni的正方形,将它们旋转45度后依次放置,使它们两两不相交且与x轴的交点横坐标最小;
思路:先求出每个正方形与X轴的交点,当前正方形与前面所有正方形相临得到一个xi,最大的xi就是交点;
判断是否可见,对于当前正方形,能挡住它的肯定是边长大于它的正方形,这样我们依次枚举它前面的正方形,求出最大的能延伸的坐标l;
再依次枚举它后面的正方形,求出最小的能延伸的坐标r,如果r>l 就是可见的; 几何,很难?很简单?
1 #include<cstdio> 2 #include<string> 3 #include<cstdlib> 4 #include<cmath> 5 #include<iostream> 6 #include<vector> 7 #include<algorithm> 8 using namespace std; 9 const double eps = 1e-8; 10 inline int dcmp(double x){ 11 return x < -eps ? -1 : x > eps; 12 } 13 inline double sqr(double x){ 14 return x*x; 15 } 16 const int N = 50+10; 17 double x[N],len[N],len2[N]; 18 vector<int > ans; 19 int n; 20 void solve(){ 21 x[0] = len2[0]/2; 22 for (int i = 1; i < n; i++) { 23 double tmp; 24 x[i] = 0; 25 for (int j = 0; j < i; j++) { 26 if (dcmp(len[i] - len[j]) < 0 ){ 27 tmp = x[j] + len2[i]; 28 }else tmp = x[j] + len2[j]; 29 if (dcmp(tmp - x[i]) > 0) x[i] = tmp; 30 } 31 } 32 ans.clear(); 33 for (int i = 0; i < n; i++){ 34 double l = x[i] - len2[i]/2, r = x[i] + len2[i]/2 ; 35 for (int j = 0; j < i; j++){ 36 if (dcmp(len[j] - len[i]) > 0){ 37 if (dcmp(x[j] + len2[j]/2 - l) > 0) l = x[j] + len2[j]/2; 38 } 39 } 40 for (int j = i+1; j < n; j++){ 41 if (dcmp(len[j] - len[i]) > 0){ 42 if (dcmp(x[j] - len2[j]/2 - r) < 0) r = x[j] - len2[j]/2; 43 } 44 } 45 if (dcmp(l - r) < 0) ans.push_back(i+1); 46 } 47 int sz = ans.size(); 48 for (int i = 0; i < sz-1; i++){ 49 printf("%d ",ans[i]); 50 }printf("%d\n",ans[sz-1]); 51 } 52 int main(){ 53 while (~scanf("%d",&n),n){ 54 for (int i = 0; i < n; i++){ 55 scanf("%lf",len+i); 56 len2[i] = sqrt( len[i]*len[i]*2 ); 57 } 58 solve(); 59 } 60 return 0; 61 }
poj 2826
题意:两条线段,求能接到多少水。
分析:细节题,一个被坑的状况,上面的线段在交点上方完全覆盖了下面的线段。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<vector> 8 #define pbk push_back 9 using namespace std; 10 const int N = 300+10; 11 const double eps = 1e-10; 12 const int maxP = 10000+10; 13 inline int dcmp(double x){ 14 return x<-eps ? -1 : x>eps; 15 } 16 inline double sqr(double x){ 17 return x*x; 18 } 19 struct Point { 20 double x,y; 21 Point(){} 22 Point (double a,double b):x(a),y(b){} 23 bool operator == (const Point &p)const{ 24 return (dcmp(x-p.x) == 0 && dcmp(y-p.y) == 0); 25 } 26 bool operator < (const Point &p)const{ 27 return dcmp(x-p.x) < 0 || (dcmp(x-p.x) == 0 && dcmp(y-p.y) < 0); 28 } 29 double operator * (const Point &p)const{ 30 return x*p.y - y*p.x; 31 } 32 double operator / (const Point &p)const{ 33 return x*p.x + y*p.y; 34 } 35 36 Point operator - (const Point &p)const{ 37 return Point(x-p.x,y-p.y); 38 } 39 Point operator + (const Point &p)const{ 40 return Point(x+p.x, y+p.y); 41 } 42 Point operator * (const double &k)const{ 43 return Point(x*k, y*k); 44 } 45 Point operator / (const double &k)const{ 46 return Point(x/k, y/k); 47 } 48 49 double len2(){ 50 return x*x + y*y; 51 } 52 double len(){ 53 return sqrt(x*x + y*y); 54 } 55 Point scale(const double &k){//变成长度为k的"向量" 56 return dcmp( len() ) ? (*this) * (k / len()) : (*this); 57 } 58 Point turnLeft(){ 59 return Point(-y,x); 60 } 61 Point turnRight(){ 62 return Point(y,-x); 63 } 64 void input(){ 65 scanf("%lf%lf",&x,&y); 66 } 67 void ot(){ 68 printf("%lf %lf\n",x,y); 69 } 70 double Distance(const Point &p){ 71 return sqrt( sqr(x-p.x) + sqr(y-p.y) ); 72 } 73 Point rotate(const Point &p,double angle ,double k=1){//绕P点k==1逆时针旋转angle; 74 Point vec = (*this) - p; 75 double Cos = cos(angle)*k, Sin = sin(angle)*k; 76 return p + Point(vec.x * Cos - vec.y * Sin, vec.x * Sin + vec.y * Cos); 77 } 78 }; 79 struct Line{ 80 Point a,b; 81 Line(){} 82 Line(Point a,Point b):a(a),b(b){} 83 84 double operator * (const Point &p)const{ 85 return (b-a) * (p-a); 86 } 87 double operator / (const Point &p)const{ 88 return (p-a) / (p-b); 89 } 90 void input(){ 91 a.input(); b.input(); 92 } 93 void ot(){ 94 a.ot(); b.ot(); 95 } 96 double len(){ 97 return a.Distance(b); 98 } 99 bool parallel(Line v){ 100 return !dcmp( (b-a)*(v.b-v.a) ); 101 } 102 103 int SegCrossSeg(const Line &v){//2中间相交,1端点相交,0没有交点 104 int d1 = dcmp( (*this) * v.a); 105 int d2 = dcmp( (*this) * v.b); 106 int d3 = dcmp( v * a ); 107 int d4 = dcmp( v * b ); 108 if ( (d1^d2) == -2 && (d3^d4) == -2 ) return 2; 109 return ( (d1 == 0 && dcmp( (*this)/v.a ) <= 0) 110 || (d2 == 0 && dcmp( (*this)/v.b ) <= 0) 111 || (d3 == 0 && dcmp( v / a ) <= 0) 112 || (d4 == 0 && dcmp( v / b ) <= 0) ); 113 } 114 115 int LineCrossSeg(const Line &v){//2相交,1共线,0相离 116 int d1 = dcmp( (*this) * v.a), d2 = dcmp( (*this) * v.b); 117 if ( (d1^d2) == -2) return 2; 118 return (d1 == 0 || d2 == 0); 119 } 120 int LineCrossLine(const Line &v){//2相交,1共线,0相离 121 if ( (*this).parallel(v)){ 122 return ( dcmp(v * a) == 0); 123 } 124 return 2; 125 } 126 Point CrossPoint(const Line &v){ 127 double s1 = v * a, s2 = v * b; 128 return ( a * s2 - b * s1) / ( s2 - s1); 129 } 130 bool IsPointOnSeg(const Point &p){ 131 return ( dcmp( (a-p)*(b-p) ) == 0 && dcmp( (p-a)/(p-b) ) <= 0 ); 132 } 133 double DisPointToSeg(Point p){//p点到线段的最短距离 134 if ( a == b) return a.Distance(p); 135 Point q = p + (a - b).turnLeft(); 136 if ( (( p - a )*( q - a )) * ( (p - b)*(q - b) ) > 0 ) { 137 return min(p.Distance(a), p.Distance(b)); 138 } 139 return fabs( (*this)*p ) / a.Distance(b) ; 140 } 141 Point PointToSeg(Point p){//p点到线段最短距离的那个点 142 if ( a == b ) return a; 143 Point q = p + (a - b).turnLeft(); 144 if ( (( p - a )*( q - a)) * ((p - b)*(q - b)) > 0){ 145 return p.Distance(a) < p.Distance(b) ? a : b; 146 } 147 return CrossPoint( Line(p,q) ); 148 } 149 double DisPointToLine(const Point &p){//点到直线的距离 150 return fabs( (*this) * p) / a.Distance(b); 151 } 152 Point PointToLine(const Point &p){//求点p垂直Line的垂心 153 return CrossPoint( Line(p,p + (a - b).turnLeft()) ); 154 } 155 Point SymPoint(const Point &p){//求p关于Line的对称点 156 return PointToLine(p) * 2 - p; 157 } 158 void Move(const double &d){//直线向左侧平移d长度 159 Point t = ( b - a ).turnLeft().scale(d); 160 a = a + t; b = b + t; 161 } 162 }; 163 struct Polygon{ 164 int n; 165 Point p[maxP]; 166 void input(){ 167 for (int i = 0; i < n; i++){ 168 p[i].input(); 169 } 170 } 171 void push(const Point &pp){ 172 p[n++] = pp; 173 } 174 void getConvex(Polygon &c){ 175 sort(p, p+n); 176 c.n = n; 177 if (n == 0) return; 178 c.p[0] = p[0]; if (n == 1) return; 179 c.p[1] = p[1]; if (n == 2) return; 180 int &top = c.n; 181 top =1; 182 for (int i = 2; i < n; i++){ 183 while (top > 0 && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0) 184 top --; 185 c.p[++top] = p[i]; 186 } 187 int tmp = top; 188 c.p[++top] = p[n-2]; 189 for (int i = n-3; i >= 0; i--){ 190 while (top > tmp && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0) 191 top --; 192 c.p[++top] = p[i]; 193 } 194 } 195 int IsPointInpolygon(const Point &pp){ 196 p[n] = p[0]; 197 int wn = 0; 198 for (int i =0; i < n; i++) { 199 if ( Line(p[i],p[i+1]).IsPointOnSeg(pp) ) { 200 if (p[i] == pp || p[i+1] == pp) return 3; 201 return 2; 202 } 203 int k = dcmp( (p[i] - pp)*(p[i+1] - pp) ); 204 int u = dcmp( p[i].y - pp.y); 205 int v = dcmp( p[i+1].y - pp.y); 206 if (k > 0 && u < 0 && v >= 0) wn++; 207 if (k < 0 && v < 0 && u >= 0) wn--; 208 } 209 return (wn != 0); 210 } 211 double CalcPerimeter(){ 212 if (n == 1) return 0; 213 double ret = p[0].Distance(p[n-1]); 214 for (int i = 0; i < n-1; i++ ){ 215 ret += p[i].Distance(p[i+1]); 216 } 217 return ret; 218 } 219 double CalcArea(){ 220 double ret = 0; 221 for (int i = 1; i < n-1; i++ ){ 222 ret += (p[i] - p[0]) * (p[i+1] - p[0]); 223 } 224 return ret * 0.5; 225 } 226 227 }; 228 Line L[2]; 229 int main(){ 230 int T;scanf("%d",&T); 231 while (T--){ 232 L[0].input(); L[1].input(); 233 if (L[0].parallel(L[1])) { 234 printf("0.00\n"); continue; 235 } 236 if (L[0].a.y<L[0].b.y) swap(L[0].a,L[0].b); 237 if (L[1].a.y<L[1].b.y) swap(L[1].a,L[1].b); 238 if (L[0].a.y == L[0].b.y || L[1].a.y == L[1].b.y){ 239 printf("0.00\n"); continue; 240 } 241 if (L[0].SegCrossSeg(L[1])){ 242 Point t = L[0].CrossPoint(L[1]); 243 if (t == L[0].a || t == L[1].a) printf("0.00\n"); 244 else { 245 int flag = L[0].a.y>L[1].a.y ? 1 : 0; 246 Point tmp = L[flag].a; 247 if (dcmp((L[flag].a - t)*(L[flag^1].a - t)) <= 0 && dcmp(L[flag^1].a.x - L[flag].a.x) <= 0){ 248 printf("0.00\n"); continue; 249 } 250 if (dcmp((L[flag].a - t)*(L[flag^1].a - t)) >= 0 && dcmp(L[flag^1].a.x - L[flag].a.x) >= 0){ 251 printf("0.00\n"); continue; 252 } 253 Line t2 = Line(tmp,tmp-Point(1,0)); 254 255 Point tmp2 = t2.CrossPoint(Line(t,L[flag^1].a)); 256 double ret = fabs((tmp2 - t) * (L[flag].a - t))/2; 257 258 printf("%.2lf\n",ret+eps); 259 } 260 }else printf("0.00\n"); 261 } 262 return 0; 263 }
poj 2074
题意:给你两条平行的线段1,2,然后再给你其他平行的线段Li,问从线段2能看到线段1的最大的连续区间;
分析:枚举线段Li得出对于线段Li在线段2上肯定不能看到线段1的区间,然后顺便把点记录下来
那么最大区间的端点肯定是上面两个区间的端点,然后枚举所有重新组合的区间,取该区间的中点看是否被上面的区间覆盖,
如果没有那么就是有效区间; 要先排除不在线段1,2之间的线段; 几何,取中点。
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<vector> 8 #define pbk push_back 9 using namespace std; 10 const int N = 300+10; 11 const double eps = 1e-10; 12 const int maxP = 10000+10; 13 inline int dcmp(double x){ 14 return x<-eps ? -1 : x>eps; 15 } 16 inline double sqr(double x){ 17 return x*x; 18 } 19 void in(double &x){ 20 char c = getchar(); 21 bool IsN = 0; 22 while (c!='-' && (c<'0' || c>'9')) c = getchar(); 23 if ( c == '-'){ 24 IsN = 1; x = 0; 25 }else x = c - '0'; 26 c = getchar(); 27 while (c>='0' && c<='9') { 28 x = x*10+c-'0'; 29 c = getchar(); 30 } 31 if (IsN) x = -x; 32 } 33 struct Point { 34 double x,y; 35 Point(){} 36 Point (double a,double b):x(a),y(b){} 37 bool operator == (const Point &p)const{ 38 return (dcmp(x-p.x) == 0 && dcmp(y-p.y) == 0); 39 } 40 bool operator < (const Point &p)const{ 41 return dcmp(x-p.x) < 0 || (dcmp(x-p.x) == 0 && dcmp(y-p.y) < 0); 42 } 43 double operator * (const Point &p)const{ 44 return x*p.y - y*p.x; 45 } 46 double operator / (const Point &p)const{ 47 return x*p.x + y*p.y; 48 } 49 50 Point operator - (const Point &p)const{ 51 return Point(x-p.x,y-p.y); 52 } 53 Point operator + (const Point &p)const{ 54 return Point(x+p.x, y+p.y); 55 } 56 Point operator * (const double &k)const{ 57 return Point(x*k, y*k); 58 } 59 Point operator / (const double &k)const{ 60 return Point(x/k, y/k); 61 } 62 63 double len2(){ 64 return x*x + y*y; 65 } 66 double len(){ 67 return sqrt(x*x + y*y); 68 } 69 Point scale(const double &k){//变成长度为k的"向量" 70 return dcmp( len() ) ? (*this) * (k / len()) : (*this); 71 } 72 Point turnLeft(){ 73 return Point(-y,x); 74 } 75 Point turnRight(){ 76 return Point(y,-x); 77 } 78 void input(){ 79 // in(x); in(y); 80 scanf("%lf%lf",&x,&y); 81 } 82 void ot(){ 83 printf("%lf %lf\n",x,y); 84 } 85 double Distance(const Point &p){ 86 return sqrt( sqr(x-p.x) + sqr(y-p.y) ); 87 } 88 Point rotate(const Point &p,double angle ,double k=1){//绕P点k==1逆时针旋转angle; 89 Point vec = (*this) - p; 90 double Cos = cos(angle)*k, Sin = sin(angle)*k; 91 return p + Point(vec.x * Cos - vec.y * Sin, vec.x * Sin + vec.y * Cos); 92 } 93 }; 94 struct Line{ 95 Point a,b; 96 Line(){} 97 Line(Point a,Point b):a(a),b(b){} 98 99 double operator * (const Point &p)const{ 100 return (b-a) * (p-a); 101 } 102 double operator / (const Point &p)const{ 103 return (p-a) / (p-b); 104 } 105 void input(){ 106 a.input(); b.input(); 107 } 108 void ot(){ 109 a.ot(); b.ot(); 110 } 111 double len(){ 112 return a.Distance(b); 113 } 114 bool parallel(Line v){ 115 return !dcmp( (b-a)*(v.b-v.a) ); 116 } 117 118 int SegCrossSeg(const Line &v){//2中间相交,1端点相交,0没有交点 119 int d1 = dcmp( (*this) * v.a); 120 int d2 = dcmp( (*this) * v.b); 121 int d3 = dcmp( v * a ); 122 int d4 = dcmp( v * b ); 123 if ( (d1^d2) == -2 && (d3^d4) == -2 ) return 2; 124 return ( (d1 == 0 && dcmp( (*this)/v.a ) <= 0) 125 || (d2 == 0 && dcmp( (*this)/v.b ) <= 0) 126 || (d3 == 0 && dcmp( v / a ) <= 0) 127 || (d4 == 0 && dcmp( v / b ) <= 0) ); 128 } 129 130 int LineCrossSeg(const Line &v){//2相交,1共线,0相离,v线段 131 int d1 = dcmp( (*this) * v.a), d2 = dcmp( (*this) * v.b); 132 if ( (d1^d2) == -2) return 2; 133 return (d1 == 0 || d2 == 0); 134 } 135 int LineCrossLine(const Line &v){//2相交,1共线,0相离 136 if ( (*this).parallel(v)){ 137 return ( dcmp(v * a) == 0); 138 } 139 return 2; 140 } 141 Point CrossPoint(const Line &v){ 142 double s1 = v * a, s2 = v * b; 143 return ( a * s2 - b * s1) / ( s2 - s1); 144 } 145 bool IsPointOnSeg(const Point &p){ 146 return ( dcmp( (a-p)*(b-p) ) == 0 && dcmp( (p-a)/(p-b) ) <= 0 ); 147 } 148 double DisPointToSeg(Point p){//p点到线段的最短距离 149 if ( a == b) return a.Distance(p); 150 Point q = p + (a - b).turnLeft(); 151 if ( (( p - a )*( q - a )) * ( (p - b)*(q - b) ) > 0 ) { 152 return min(p.Distance(a), p.Distance(b)); 153 } 154 return fabs( (*this)*p ) / a.Distance(b) ; 155 } 156 Point PointToSeg(Point p){//p点到线段最短距离的那个点 157 if ( a == b ) return a; 158 Point q = p + (a - b).turnLeft(); 159 if ( (( p - a )*( q - a)) * ((p - b)*(q - b)) > 0){ 160 return p.Distance(a) < p.Distance(b) ? a : b; 161 } 162 return CrossPoint( Line(p,q) ); 163 } 164 double DisPointToLine(const Point &p){//点到直线的距离 165 return fabs( (*this) * p) / a.Distance(b); 166 } 167 Point PointToLine(const Point &p){//求点p垂直Line的垂心 168 return CrossPoint( Line(p,p + (a - b).turnLeft()) ); 169 } 170 Point SymPoint(const Point &p){//求p关于Line的对称点 171 return PointToLine(p) * 2 - p; 172 } 173 void Move(const double &d){//直线向左侧平移d长度 174 Point t = ( b - a ).turnLeft().scale(d); 175 a = a + t; b = b + t; 176 } 177 }; 178 struct Polygon{ 179 int n; 180 Point p[maxP]; 181 void input(){ 182 for (int i = 0; i < n; i++){ 183 p[i].input(); 184 } 185 } 186 void push(const Point &pp){ 187 p[n++] = pp; 188 } 189 void getConvex(Polygon &c){ 190 sort(p, p+n); 191 c.n = n; 192 if (n == 0) return; 193 c.p[0] = p[0]; if (n == 1) return; 194 c.p[1] = p[1]; if (n == 2) return; 195 int &top = c.n; 196 top =1; 197 for (int i = 2; i < n; i++){ 198 while (top > 0 && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0) 199 top --; 200 c.p[++top] = p[i]; 201 } 202 int tmp = top; 203 c.p[++top] = p[n-2]; 204 for (int i = n-3; i >= 0; i--){ 205 while (top > tmp && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0) 206 top --; 207 c.p[++top] = p[i]; 208 } 209 } 210 int IsPointInpolygon(const Point &pp){//包括凹多边形 211 p[n] = p[0]; 212 int wn = 0; 213 for (int i =0; i < n; i++) { 214 if ( Line(p[i],p[i+1]).IsPointOnSeg(pp) ) { 215 if (p[i] == pp || p[i+1] == pp) return 3; 216 return 2; 217 } 218 int k = dcmp( (p[i] - pp)*(p[i+1] - pp) ); 219 int u = dcmp( p[i].y - pp.y); 220 int v = dcmp( p[i+1].y - pp.y); 221 if (k > 0 && u < 0 && v >= 0) wn++; 222 if (k < 0 && v < 0 && u >= 0) wn--; 223 } 224 return (wn != 0); 225 } 226 bool IsPointInConvex(const Point &pp){ 227 bool s[3] = {false, false, false}; 228 p[n] = p[0]; 229 for (int i = 0; i < n; i++){ 230 s[dcmp(( p[i+1] - pp ) * ( p[i] - pp )) + 1] = true; 231 if ( s[0] && s[2] ) return false; //点在外面. 232 if ( s[1] ) return true;//点在边上; 233 } 234 return true; 235 } 236 double CalcPerimeter(){ 237 if (n == 1) return 0; 238 double ret = p[0].Distance(p[n-1]); 239 for (int i = 0; i < n-1; i++ ){ 240 ret += p[i].Distance(p[i+1]); 241 } 242 return ret; 243 } 244 double CalcArea(){ 245 double ret = 0; 246 for (int i = 1; i < n-1; i++ ){ 247 ret += (p[i] - p[0]) * (p[i+1] - p[0]); 248 } 249 return ret * 0.5; 250 } 251 bool IsConvex(){ 252 bool s[3] = {false, false, false}; 253 p[n] = p[0], p[n+1] = p[1]; 254 for (int i = 0; i < n; i++){ 255 s[dcmp(( p[i+1] - p[i] ) * ( p[i+2] - p[i] )) + 1] = true; 256 if (s[0] && s[2]) return false;//如果-1,和1都出现过; 257 } 258 return true; 259 } 260 261 }H; 262 int n; 263 vector<Point> seg; 264 vector<double > Lx; 265 Line t1,t2,L[N]; 266 void solve(){ 267 double x1,x2,y; 268 double ans = 0; 269 seg.clear(); Lx.clear(); 270 Lx.push_back(t2.a.x); Lx.pbk(t2.b.x); 271 272 for (int i = 0; i < n; i++){ 273 cin>>x1>>x2>>y; 274 L[i] = Line(Point(x1,y),Point(x2,y)); 275 } 276 for (int i = 0; i < n; i++){ 277 if (dcmp(L[i].a.y - t1.a.y) >= 0) continue; 278 if (dcmp(L[i].a.y - t2.a.y) < 0) continue; 279 280 Line tp1 = Line(t1.a,L[i].b); 281 Line tp2 = Line(t1.b,L[i].a); 282 Point p1,p2; 283 p1 = tp1.CrossPoint(t2); 284 Lx.pbk(p1.x); 285 p2 = tp2.CrossPoint(t2); 286 Lx.pbk(p2.x); 287 seg.pbk(Point(p2.x,p1.x)); 288 } 289 sort(Lx.begin(),Lx.end()); 290 for (int i = 0; i+1 < Lx.size(); i++){ 291 if (dcmp(Lx[i] - t2.a.x) < 0) continue; 292 if (dcmp(Lx[i+1] - t2.b.x) > 0) break; 293 double tx = ( Lx[i] + Lx[i+1] ) / 2; 294 int flag = 1; 295 for (int j = 0; j < seg.size() && flag; j++){ 296 if (dcmp(seg[j].x - tx) < 0 && dcmp(seg[j].y - tx) > 0) flag = 0; 297 } 298 if (flag){ 299 if (dcmp(Lx[i+1] - Lx[i] - ans) > 0) ans = Lx[i+1] - Lx[i]; 300 } 301 } 302 if (dcmp(ans) == 0) printf("No View\n"); 303 else printf("%.2lf\n",ans); 304 } 305 int main(){ 306 double x1,x2,y; 307 while (cin>>x1>>x2>>y){ 308 if (dcmp(x1) == 0 && dcmp(x2) == 0 && dcmp(y) == 0) break; 309 t1.a = Point(x1,y); t1.b = Point(x2,y); 310 cin>>x1>>x2>>y; 311 t2.a = Point(x1,y); t2.b = Point(x2,y); 312 cin>>n; 313 solve(); 314 } 315 return 0; 316 }
面:
poj 1228
题意:原本有一个凸包(规则),但是凸包上的一些点不见了,问剩下的点组成的凸包能否确定原先的凸包。
分析:要使剩下的点组成的凸包确定原先的凸包,那么也就是说不管对剩下的凸包在哪里加点都不能形成一个新的面积更大的凸包(剩下的所有点必须在新凸包上),
也就是现在凸包上的每一条线至少有3个点;
如果剩下的点组成的凸包没有面积,或者不能组成凸包,肯定也不行;
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<vector> 8 #define pbk push_back 9 using namespace std; 10 const int N = 300+10; 11 const double eps = 1e-10; 12 const double PI = acos(-1.0); 13 const int maxP = 10000+10; 14 inline int dcmp(double x){ 15 return x<-eps ? -1 : x>eps; 16 } 17 inline double sqr(double x){ 18 return x*x; 19 } 20 void in(double &x){ 21 char c = getchar(); 22 bool IsN = 0; 23 while (c!='-' && (c<'0' || c>'9')) c = getchar(); 24 if ( c == '-'){ 25 IsN = 1; x = 0; 26 }else x = c - '0'; 27 c = getchar(); 28 while (c>='0' && c<='9') { 29 x = x*10+c-'0'; 30 c = getchar(); 31 } 32 if (IsN) x = -x; 33 } 34 struct Point { 35 double x,y; 36 Point(){} 37 Point (double a,double b):x(a),y(b){} 38 bool operator == (const Point &p)const{ 39 return (dcmp(x-p.x) == 0 && dcmp(y-p.y) == 0); 40 } 41 bool operator < (const Point &p)const{ 42 return dcmp(x-p.x) < 0 || (dcmp(x-p.x) == 0 && dcmp(y-p.y) < 0); 43 } 44 double operator * (const Point &p)const{ 45 return x*p.y - y*p.x; 46 } 47 double operator / (const Point &p)const{ 48 return x*p.x + y*p.y; 49 } 50 51 Point operator - (const Point &p)const{ 52 return Point(x-p.x,y-p.y); 53 } 54 Point operator + (const Point &p)const{ 55 return Point(x+p.x, y+p.y); 56 } 57 Point operator * (const double &k)const{ 58 return Point(x*k, y*k); 59 } 60 Point operator / (const double &k)const{ 61 return Point(x/k, y/k); 62 } 63 64 double len2(){ 65 return x*x + y*y; 66 } 67 double len(){ 68 return sqrt(x*x + y*y); 69 } 70 Point scale(const double &k){//变成长度为k的"向量" 71 return dcmp( len() ) ? (*this) * (k / len()) : (*this); 72 } 73 Point turnLeft(){ 74 return Point(-y,x); 75 } 76 Point turnRight(){ 77 return Point(y,-x); 78 } 79 void input(){ 80 // in(x); in(y); 81 scanf("%lf%lf",&x,&y); 82 } 83 void ot(){ 84 printf("%lf %lf\n",x,y); 85 } 86 double Distance(const Point &p){ 87 return sqrt( sqr(x-p.x) + sqr(y-p.y) ); 88 } 89 Point rotate(const Point &p,double angle ,double k=1){//绕P点k==1逆时针旋转angle; 90 Point vec = (*this) - p; 91 double Cos = cos(angle)*k, Sin = sin(angle)*k; 92 return p + Point(vec.x * Cos - vec.y * Sin, vec.x * Sin + vec.y * Cos); 93 } 94 }; 95 struct Line{ 96 Point a,b; 97 Line(){} 98 Line(Point a,Point b):a(a),b(b){} 99 100 double operator * (const Point &p)const{ 101 return (b-a) * (p-a); 102 } 103 double operator / (const Point &p)const{ 104 return (p-a) / (p-b); 105 } 106 void input(){ 107 a.input(); b.input(); 108 } 109 void ot(){ 110 a.ot(); b.ot(); 111 } 112 double len(){ 113 return a.Distance(b); 114 } 115 bool parallel(Line v){ 116 return !dcmp( (b-a)*(v.b-v.a) ); 117 } 118 119 int SegCrossSeg(const Line &v){//2中间相交,1端点相交,0没有交点 120 int d1 = dcmp( (*this) * v.a); 121 int d2 = dcmp( (*this) * v.b); 122 int d3 = dcmp( v * a ); 123 int d4 = dcmp( v * b ); 124 if ( (d1^d2) == -2 && (d3^d4) == -2 ) return 2; 125 return ( (d1 == 0 && dcmp( (*this)/v.a ) <= 0) 126 || (d2 == 0 && dcmp( (*this)/v.b ) <= 0) 127 || (d3 == 0 && dcmp( v / a ) <= 0) 128 || (d4 == 0 && dcmp( v / b ) <= 0) ); 129 } 130 131 int LineCrossSeg(const Line &v){//2相交,1共线,0相离,v线段 132 int d1 = dcmp( (*this) * v.a), d2 = dcmp( (*this) * v.b); 133 if ( (d1^d2) == -2) return 2; 134 return (d1 == 0 || d2 == 0); 135 } 136 int LineCrossLine(const Line &v){//2相交,1共线,0相离 137 if ( (*this).parallel(v)){ 138 return ( dcmp(v * a) == 0); 139 } 140 return 2; 141 } 142 Point CrossPoint(const Line &v){ 143 double s1 = v * a, s2 = v * b; 144 return ( a * s2 - b * s1) / ( s2 - s1); 145 } 146 bool IsPointOnSeg(const Point &p){ 147 return ( dcmp( (a-p) * (b-p) ) == 0 && dcmp( (p-a)/(p-b) ) <= 0 ); 148 } 149 double DisPointToSeg(Point p){//p点到线段的最短距离 150 if ( a == b) return a.Distance(p); 151 Point q = p + (a - b).turnLeft(); 152 if ( (( p - a )*( q - a )) * ( (p - b)*(q - b) ) > 0 ) { 153 return min(p.Distance(a), p.Distance(b)); 154 } 155 return fabs( (*this)*p ) / a.Distance(b) ; 156 } 157 Point PointToSeg(Point p){//p点到线段最短距离的那个点 158 if ( a == b ) return a; 159 Point q = p + (a - b).turnLeft(); 160 if ( (( p - a )*( q - a)) * ((p - b)*(q - b)) > 0){ 161 return p.Distance(a) < p.Distance(b) ? a : b; 162 } 163 return CrossPoint( Line(p,q) ); 164 } 165 double DisPointToLine(const Point &p){//点到直线的距离 166 return fabs( (*this) * p) / a.Distance(b); 167 } 168 Point PointToLine(const Point &p){//求点p垂直Line的垂心 169 return CrossPoint( Line(p,p + (a - b).turnLeft()) ); 170 } 171 Point SymPoint(const Point &p){//求p关于Line的对称点 172 return PointToLine(p) * 2 - p; 173 } 174 void Move(const double &d){//直线向左侧平移d长度 175 Point t = ( b - a ).turnLeft().scale(d); 176 a = a + t; b = b + t; 177 } 178 }; 179 struct Polygon{ 180 int n; 181 Point p[maxP]; 182 void input(){ 183 for (int i = 0; i < n; i++){ 184 p[i].input(); 185 } 186 } 187 void push(const Point &pp){ 188 p[n++] = pp; 189 } 190 191 void getConvex(Polygon &c){ 192 sort(p, p+n); 193 c.n = n; 194 if (n == 0) return; 195 c.p[0] = p[0]; if (n == 1) return; 196 c.p[1] = p[1]; if (n == 2) return; 197 int &top = c.n; 198 top =1; 199 for (int i = 2; i < n; i++){ 200 while (top > 0 && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0) 201 top --; 202 c.p[++top] = p[i]; 203 } 204 int tmp = top; 205 c.p[++top] = p[n-2]; 206 for (int i = n-3; i >= 0; i--){ 207 while (top > tmp && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0) 208 top --; 209 c.p[++top] = p[i]; 210 } 211 } 212 int IsPointInpolygon(const Point &pp){//包括凹多边形 213 p[n] = p[0]; 214 int wn = 0; 215 for (int i =0; i < n; i++) { 216 if ( Line(p[i],p[i+1]).IsPointOnSeg(pp) ) { 217 if (p[i] == pp || p[i+1] == pp) return 3; 218 return 2; 219 } 220 int k = dcmp( (p[i] - pp)*(p[i+1] - pp) ); 221 int u = dcmp( p[i].y - pp.y); 222 int v = dcmp( p[i+1].y - pp.y); 223 if (k > 0 && u < 0 && v >= 0) wn++; 224 if (k < 0 && v < 0 && u >= 0) wn--; 225 } 226 return (wn != 0); 227 } 228 bool IsPointInConvex(const Point &pp){ 229 bool s[3] = {false, false, false}; 230 p[n] = p[0]; 231 for (int i = 0; i < n; i++){ 232 s[dcmp(( p[i+1] - pp ) * ( p[i] - pp )) + 1] = true; 233 if ( s[0] && s[2] ) return false; //点在外面. 234 if ( s[1] ) return true;//点在边上; 235 } 236 return true; 237 } 238 double CalcPerimeter(){ 239 if (n == 1) return 0; 240 double ret = p[0].Distance(p[n-1]); 241 for (int i = 0; i < n-1; i++ ){ 242 ret += p[i].Distance(p[i+1]); 243 } 244 return ret; 245 } 246 double CalcArea(){ 247 double ret = 0; 248 for (int i = 1; i < n-1; i++ ){ 249 ret += (p[i] - p[0]) * (p[i+1] - p[0]); 250 } 251 return ret * 0.5; 252 } 253 bool IsConvex(){ 254 bool s[3] = {false, false, false}; 255 p[n] = p[0], p[n+1] = p[1]; 256 for (int i = 0; i < n; i++){ 257 s[dcmp(( p[i+1] - p[i] ) * ( p[i+2] - p[i] )) + 1] = true; 258 if (s[0] && s[2]) return false;//如果-1,和1都出现过; 259 } 260 return true; 261 } 262 263 }H,H2; 264 int n; 265 int check(Line L){ 266 for (int i = 0; i < H.n; i++ ){ 267 if (L.IsPointOnSeg(H.p[i]) && !(H.p[i] == L.a) && !(H.p[i] == L.b)) return 1; 268 } 269 return 0; 270 } 271 void solve(){ 272 H.getConvex(H2); 273 H2.p[H2.n] = H2.p[0]; 274 int flag = 1; 275 if (dcmp( H2.CalcArea() ) <= 0) flag = 0; 276 for (int i = 0; i < H2.n && flag; i++ ){ 277 if ( check( Line(H2.p[i],H2.p[i+1]) ) == 0 ) flag = 0; 278 } 279 puts(flag ? "YES":"NO"); 280 281 } 282 int main(){ 283 int T; scanf("%d",&T); 284 while (T--){ 285 scanf("%d",&H.n); 286 H.input(); 287 solve(); 288 } 289 return 0; 290 }