计算几何

点,线:

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

 

面:

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 }
View Code

 

你可能感兴趣的:(计算)