计算几何

poj 计算几何题集:    

http://apps.hi.baidu.com/share/detail/6748938     

http://hi.baidu.com/novosbirsk/blog/item/723a9727a9ab8804918f9dca.html

1.poj 2318   TOYS

 点与格子左右两块板的叉乘小于0,然后二分查找     

注意乘法时,int型会溢出 – -!    

代码
1#include <iostream>
2#include <cstdio>
3#include <cstring>
4#include <cmath>
5
6using namespace std;
7
8struct point{ int x, y; }toy[5010];
9struct line{ point u, d;}card[5010];
10
11int ans[5010];
12int n, m;
13
14__int64 mul(point p0, point p1, point p2){
15 return (__int64)(p1.x-p0.x)*(p2.y-p0.y) - (__int64)(p1.y-p0.y)*(p2.x-p0.x);
16}
17
18int find(int a, int b){
19 int l, r, mid;
20 __int64 mul1, mul2;
21 point pp;
22 pp.x = a;
23 pp.y = b;
24 l = 0;
25 r = n+1;
26 while(l<=r){
27 mid = (l+r)>>1;
28 mul1 = mul(card[mid].d, card[mid].u, pp);
29 mul2 = mul(card[mid+1].d, card[mid+1].u, pp);
30 if(mul1 * mul2 <= 0) break;
31 if(mul1<0 && mul2<0){
32 l = mid + 1;
33 }else {
34 r = mid - 1;
35 }
36 }
37 return mid;
38}
39
40int main(){
41// freopen("c:/aaa.txt", "r", stdin);
42 int i, j, a, b, ca=0;
43 while(scanf("%d", &n), n){
44 if(ca != 0) putchar('\n');
45 ++ca;
46 scanf("%d %d %d %d %d", &m, &card[0].u.x, &card[0].u.y, &card[n+1].d.x, &card[n+1].d.y);
47 card[0].u.x--;
48 card[n+1].d.x++;
49 card[0].d.x = card[0].u.x;
50 card[0].d.y = card[n+1].d.y;
51 card[n+1].u.x = card[n+1].d.x;
52 card[n+1].u.y = card[0].u.y;
53 for(i=1; i<=n; ++i){
54 scanf("%d %d", &card[i].u.x, &card[i].d.x);
55 card[i].u.y = card[0].u.y;
56 card[i].d.y = card[n+1].d.y;
57 }
58
59 memset(ans, 0, sizeof(ans));
60 for(i=0; i<m; ++i){
61 scanf("%d %d", &a, &b);
62 ans[find(a, b)] ++;
63 }
64
65 for(i=0; i<=n; ++i){
66 printf("%d: %d\n", i, ans[i]);
67 }
68 }
69 return 0;
70}

2.poj 2398 Toy storage

处理方法同poj2318   

代码
1#include <iostream>
2#include <cstdio>
3#include <cstring>
4#include <cmath>
5#include <algorithm>
6
7using namespace std;
8
9struct point{ int x, y; }toy[5010];
10struct line{ point u, d;}card[5010];
11
12int ans[5010];
13int hash[5010];
14int n, m;
15
16__int64 mul(point p0, point p1, point p2){
17 return (__int64)(p1.x-p0.x)*(p2.y-p0.y) - (__int64)(p1.y-p0.y)*(p2.x-p0.x);
18}
19
20bool cmp(line x, line y) { return x.u.x < y.u.x; }
21
22int find(int a, int b){
23 int l, r, mid;
24 __int64 mul1, mul2;
25 point pp;
26 pp.x = a;
27 pp.y = b;
28 l = 0;
29 r = n+1;
30 while(l<=r){
31 mid = (l+r)>>1;
32 mul1 = mul(card[mid].d, card[mid].u, pp);
33 mul2 = mul(card[mid+1].d, card[mid+1].u, pp);
34 if(mul1 * mul2 < 0) break;
35 if(mul1<0 && mul2<0){
36 l = mid + 1;
37 }else {
38 r = mid - 1;
39 }
40 }
41 return mid;
42}
43
44int main(){
45// freopen("c:/aaa.txt", "r", stdin);
46 int i, j, a, b, big;
47 int temp;
48 while(scanf("%d", &n), n){
49 scanf("%d %d %d %d %d", &m, &card[0].u.x, &card[0].u.y, &card[n+1].d.x, &card[n+1].d.y);
50 card[0].u.x--;
51 card[n+1].d.x++;
52 card[0].d.x = card[0].u.x;
53 card[0].d.y = card[n+1].d.y;
54 card[n+1].u.x = card[n+1].d.x;
55 card[n+1].u.y = card[0].u.y;
56
57 for(i=1; i<=n; ++i){
58 scanf("%d %d", &card[i].u.x, &card[i].d.x);
59 card[i].u.y = card[0].u.y;
60 card[i].d.y = card[n+1].d.y;
61 }
62 sort(card+1, card+n+1, cmp);
63
64 memset(ans, 0, sizeof(ans));
65 for(i=0; i<m; ++i){
66 scanf("%d %d", &a, &b);
67 temp = find(a, b);
68 ans[temp] ++;
69 }
70
71 memset(hash, 0, sizeof(hash));
72 big = 0;
73 for(i=0; i<=n; ++i){
74 hash[ans[i]] ++;
75 if(ans[i] > big) big = ans[i];
76 }
77 puts("Box");
78 for(i=1; i<=big; ++i){
79 if(hash[i]){
80 printf("%d: %d\n", i, hash[i]);
81 }
82 }
83 }
84 return 0;
85}

3.poj 1556 The Doors

即求左右两端两点的最短距离。中间求出可以直接可达的两点的距离   

关键是线段是否相交的判断 .g++会wa,c++提交

代码
1#include <iostream>
2#include <cmath>
3#include <cstdio>
4#include <queue>
5#define inf 1000000000
6using namespace std;
7
8struct Node{ double x, pos[6]; }wall[22];
9
10double mp[80][80];
11int n;
12
13double dis(double x1, double y1, double x2, double y2){
14 return sqrt( (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) );
15}
16
17double xmul(double x1, double y1, double x2, double y2, double x3, double y3){
18 return (x2 - x1)*(y3 - y1) - (y2 - y1)*(x3 - x1);
19}
20
21double min(double a, double b){ return a < b ? a : b; }
22double max(double a, double b){ return a > b ? a : b; }
23
24bool iscross(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
25 if(max(x1, x2) >= min(x3, x4) &&
26 max(x3, x4) >= min(x1, x2) &&
27 max(y1, y2) >= min(y3, y4) &&
28 max(y3, y4) >= min(y1, y2) &&
29 xmul(x1, y1, x2, y2, x3, y3)*xmul(x1, y1, x2, y2, x4, y4) <= 0 &&
30 xmul(x3, y3, x4, y4, x1, y1)*xmul(x3, y3, x4, y4, x2, y2) <= 0 )
31 return 1;
32 return 0;
33}
34
35bool Direct(int i, int j, int k, int h){
36 int ii, jj;
37 for(ii=i+1; ii<k; ++ii){
38 for(jj=0; jj<5; jj+=2){
39 if(iscross(wall[i].x, wall[i].pos[j], wall[k].x, wall[k].pos[h],
40 wall[ii].x, wall[ii].pos[jj], wall[ii].x, wall[ii].pos[jj+1]) )
41 return 0;
42 }
43 }
44 return 1;
45}
46
47void init(){
48 int i, j;
49 for(i=1; i<=n; ++i){
50 scanf("%lf %lf %lf %lf %lf", &wall[i].x, &wall[i].pos[1], &wall[i].pos[2], &wall[i].pos[3], &wall[i].pos[4]);
51 wall[i].pos[5] = 10;
52 wall[i].pos[0] = 0;
53 }
54
55 wall[0].x = 0;
56 wall[0].pos[0] = 5;
57 wall[n+1].x = 10;
58 wall[n+1].pos[0] = 5;
59
60 for(i=0; i<80; ++i){
61 for(j=0; j<80; ++j){
62 mp[i][j] = inf;
63 }
64 }
65}
66
67void intograph(){
68 int i, j, k, h;
69 for(i=1; i<=n; ++i){
70 for(j=1; j<5; ++j){
71 if(Direct(0, 0, i, j))
72 mp[(i-1)*4+j][0] = mp[0][(i-1)*4+j] = dis(0, 5, wall[i].x, wall[i].pos[j]);
73 if(Direct(i, j, n+1, 0) )
74 mp[(i-1)*4+j][n*4+1] = mp[4*n+1][(i-1)*4+j] = dis(wall[i].x, wall[i].pos[j], 10, 5);
75 if(i<n){
76 for(k=1; k<5; ++k){
77 mp[i*4+k][(i-1)*4+j] = mp[(i-1)*4+j][i*4+k] = dis(wall[i].x, wall[i].pos[j], wall[i+1].x, wall[i+1].pos[k]);
78 }
79 }
80 for(k=i+2; k<=n; ++k){
81 for(h=1; h<5; ++h){
82 if(Direct(i, j, k, h)){
83 mp[(k-1)*4+h][(i-1)*4+j] = mp[(i-1)*4+j][(k-1)*4+h] = dis(wall[i].x, wall[i].pos[j], wall[k].x, wall[k].pos[h]);
84 }
85 }
86 }
87 }
88 }
89}
90
91void spfa(){
92 int i;
93 double MinDis[80];
94 bool mark[80];
95 queue<int> Q;
96
97 for(i=0; i<80; ++i)
98 MinDis[i] = inf, mark[i] = 0;
99 Q.push(0);
100 mark[0] = 1;
101 MinDis[0] = 0;
102 while(!Q.empty()){
103 int u;
104 u = Q.front();
105 Q.pop();
106 mark[u] = 0;
107 for(i=0; i<=4*n+1; ++i){
108 if(MinDis[i]>MinDis[u] + mp[u][i]){
109 MinDis[i] = MinDis[u] + mp[u][i];
110 if(!mark[i]){
111 Q.push(i);
112 mark[i] = 1;
113 }
114 }
115 }
116 }
117 printf("%.2f\n", MinDis[4*n+1]);
118}
119
120int main(){
121// freopen("c:/aaa.txt", "r", stdin);
122 while(scanf("%d", &n)!=EOF){
123 if(n<0) break;
124 init();
125 if(Direct(0, 0, n+1, 0)){
126 printf("10.00\n");
127 continue;
128 }
129 intograph();
130 spfa();
131 }
132 return 0;
133}

4.poj 1696 Space Ant

以最左下角点位起始点,不断生成剩下点的凸包。

代码
1#include <iostream>
2#include <cstdio>
3#include <algorithm>
4#include <cstring>
5using namespace std;
6
7struct Node{ int idx, x, y; }pt[110], now;
8int n, ans[110], cnt;
9bool mark[110];
10
11bool cmp(Node a, Node b){
12 if(a.y == b.y) return a.x < b.x;
13 else return a.y < b.y;
14}
15
16int xmul(Node a, Node b, Node c){
17 int x0, y0, x1, y1, x2, y2;
18 x0 = a.x; y0 = a.y;
19 x1 = b.x; y1 = b.y;
20 x2 = c.x; y2 = c.y;
21 return (x1 - x0)*(y2 - y0) - (y1 - y0)*(x2 - x0);
22}
23
24int min(int a, int b){ return a < b ? a : b; }
25int max(int a, int b){ return a > b ? a : b; }
26
27bool suit(Node a, Node b){
28 if( xmul(now, a, b)>0 ) return 1;
29 else if(xmul(now, a, b) == 0){
30 if(a.x>=min(now.x,b.x) && a.x<=max(now.x,b.x) &&
31 a.y>=min(now.y,b.y) && a.y<=max(now.y,b.y) )
32 return 1;
33 }
34 return 0;
35}
36
37void init(){
38 int i;
39 scanf("%d", &n);
40 for(i=0; i<n; ++i){
41 scanf("%d %d %d", &pt[i].idx, &pt[i].x, &pt[i].y);
42 }
43 sort(pt, pt+n, cmp);
44 memset(mark, 0, sizeof(mark));
45 cnt = 0;
46 ans[cnt++] = pt[0].idx;
47 mark[pt[0].idx] = 1;
48 now = pt[0];
49}
50
51void solve(){
52 int i, j, k;
53 for(i=0; i<n-1; ++i){
54 for(j=0; j<n; ++j){
55 if(!mark[pt[j].idx]){
56 for(k=0; k<n; ++k){
57 if(k!=j && !mark[pt[k].idx] && !suit(pt[j], pt[k]))
58 break;
59 }
60 if(k==n){
61 ans[cnt++] = pt[j].idx;
62 mark[pt[j].idx] = 1;
63 now = pt[j];
64 }
65 }
66 }
67 }
68 printf("%d", cnt);
69 for(i=0; i<cnt; ++i){
70 printf(" %d", ans[i]);
71 }
72 printf("\n");
73}
74
75int main(){
76// freopen("c:/aaa.txt", "r", stdin);
77 int T;
78 scanf("%d", &T);
79 while(T--){
80 init();
81 solve();
82 }
83 return 0;
84}

5.hdoj 2150 Pipe

判断线段是否相交时,两个叉乘的乘积会超出int,- -!

代码
1 &nbsp;
2 #include <iostream>
3 #include <vector>
4 #include <utility>
5 #include <algorithm>
6  using namespace std;
7
8 struct Node{
9 vector<pair<int, int> >vec;
10 int sz;
11 }qudao[35];
12
13 int n;
14
15 int xmul(int x1, int y1, int x2, int y2, int x3, int y3){
16 return (x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1);
17 }
18
19 int min(int a, int b){ return a < b ? a : b; }
20 int max(int a, int b){ return a > b ? a : b; }
21
22 bool iscross(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
23 if(max(x1, x2) >= min(x3, x4) &&
24 max(x3, x4) >= min(x1, x2) &&
25 max(y1, y2) >= min(y3, y4) &&
26 max(y3, y4) >= min(y1, y2) &&
27 (__int64)xmul(x1, y1, x2, y2, x3, y3)*(__int64)xmul(x1, y1, x2, y2, x4, y4) <= 0 &&
28 (__int64)xmul(x3, y3, x4, y4, x1, y1)*(__int64)xmul(x3, y3, x4, y4, x2, y2) <= 0 )
29 return 1;
30 return 0;
31 }
32
33 void init(){
34 int i, j, a, b, m;
35 for(i=0; i<n; ++i){
36 qudao[i].vec.clear();
37 }
38
39 for(i=0; i<n; ++i){
40 scanf("%d", &m);
41 qudao[i].sz = m;
42 for(j=0; j<m; ++j){
43 scanf("%d %d", &a, &b);
44 qudao[i].vec.push_back(make_pair(a, b));
45 }
46 }
47 }
48
49 void solve(){
50 int i, j, k, h;
51 bool flag = 0;
52 for(i=1; i<n; ++i){
53 for(j=1; j<qudao[i].sz; ++j){
54 for(k=0; k<i; ++k){
55 for(h=1; h<qudao[k].sz; ++h){
56 if(iscross(qudao[i].vec[j].first, qudao[i].vec[j].second, qudao[i].vec[j-1].first, qudao[i].vec[j-1].second,
57 qudao[k].vec[h].first, qudao[k].vec[h].second, qudao[k].vec[h-1].first, qudao[k].vec[h-1].second) ){
58 flag = 1;
59 break;
60 }
61 }
62 if(flag) break;
63 }
64 if(flag) break;
65 }
66 if(flag) break;
67 }
68
69 if(flag) puts("Yes");
70 else puts("No");
71 }
72
73 int main(){
74 // freopen("c:/aaa.txt", "r", stdin);
75 while(scanf("%d", &n)!=EOF){
76 init();
77 solve();
78 }
79 return 0;
80 }

6.hdoj 2202 最大三角形 

最大三角形的三个点都在土包上。但三角形的三边都可能不在凸包上!(我之前以为三角形的一边一定在凸包上)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

int n;
struct Point{ double x, y; }pt[50005];

double dis(Point a, Point b){ 
	double temp;
	temp = (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
	return sqrt(temp); 
}

double xmul(Point a, Point b, Point c){
	double x1, y1, x2, y2;
	x1 = b.x - a.x;
	y1 = b.y - a.y;
	x2 = c.x - a.x;
	y2 = c.y - a.y;
	return x1 * y2 - y1 * x2;
}

double triangleArea(Point a, Point b, Point c){
	Point p1, p2;
	p1.x = a.x - c.x; p1.y = a.y - c.y;
	p2.x = b.x - c.x; p2.y = b.y - c.y;
	return fabs(p1.x * p2.y - p1.y * p2.x) / 2.0;
}

bool cmp(Point a, Point b){
	if(xmul(pt[1], a, b) != 0) return xmul(pt[1], a, b) > 0;
	else return dis(pt[1], a) < dis(pt[1], b);
}


Point stack[50005];
int top;


void init(){
	int i, k;
	Point p;

	for(i=1; i<=n; ++i) scanf("%lf %lf", &pt[i].x, &pt[i].y);

	k = 1; //找出左下角的点
	for(i=2; i<=n; ++i){
		if(pt[i].y < pt[k].y || (pt[i].y == pt[k].y && pt[i].x < pt[k].x)){
			k = i;
		}
	}
	p = pt[k]; pt[k] = pt[1]; pt[1] = p;

	sort(pt+2, pt+n+1, cmp);
}


void solve(){
	int i, j, k, a, b;
	double maxArea, tpArea;
	Point p1, p2;
	top = 0;
	stack[++top] = pt[1];
	stack[++top] = pt[2];
	for(i=3; i<=n; ++i){
		while(xmul(stack[top-1], stack[top], pt[i]) <= 0){
			-- top;
			if(top < 2) break;
		}
		stack[++top] = pt[i];
	}

	maxArea = 0;
	for(i=1; i<=top-2; ++i) {
		for(j=i+1; j<=top-1; ++j) {
			for(k=j+1; k<=top; ++k) {
				tpArea = triangleArea(stack[i], stack[j], stack[k]);
				if(tpArea > maxArea) maxArea = tpArea;
			}
		}
	}
	printf("%.2lf\n", maxArea);
}



int main(){
//	freopen("c:/aaa.txt", "r", stdin);
	int i;
	while(scanf("%d", &n)!=EOF){
		init();
		solve();
	}
	return 0;
}

 

 

 

 

 

posted on 2010-11-13 09:32  CrazyAC  阅读(314)  评论(0编辑  收藏  举报