POJ 1873(计算几何初步——位运算枚举,求凸包)

这道题很水很水,由于数据范围很小,所以根本不用搜索。

直接位运算枚举就行了。不过要注意一点:

凸包点数小于3的情况需特判。

好了,贴代码....

View Code
  1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<queue>
5 #include<vector>
6 #include<map>
7 #include<set>
8 #include<cmath>
9 #include<complex>
10 #include<algorithm>
11 #define EPS 1e-10
12 #define largty(x,y) (x-EPS)>(y)
13 #define smalty(x,y) (x+EPS)<(y)
14 #define nlargty(x,y) (x-EPS)<(y)
15 #define nsmalty(x,y) (x+EPS)>(y)
16 #define equal(x,y) (nlargty(x,y) && (nsmalt(x,y)))
17 #define max(a,b) (a)>(b)?(a):(b)
18 #define min(a,b) (a)<(b)?(a):(b)
19 #define MAXN 20
20 using namespace std;
21 struct point {
22 double x,y;
23 int value;
24 double length;
25 }tree[MAXN],convex[MAXN],data[MAXN];
26 point start;
27 int T;
28
29 inline double p_distance(point &p, point &q)
30 {
31 return sqrt(pow(q.x - p.x,2) + pow(q.y - p.y,2));
32 }
33
34 inline double cross(const point &p1, const point &p2, const point &q1, const point &q2)
35 {
36 return (q2.y - q1.y)*(p2.x - p1.x) - (q2.x - q1.x)*(p2.y - p1.y);
37 }
38
39 inline bool cmp1(const point &p, const point &q)//选择Y-X排序下最小的点
40 {
41 return p.y < q.y || (p.y == q.y && p.x < q.x);
42 }
43
44 inline bool cmp2(const point &a, const point &b)//逆时针排序,极角相同则距离短的排前面
45 {
46 point origin;
47 origin = start;
48 return cross(origin,a,origin,b) > 0 || (cross(origin,a,origin,b) == 0 && fabs(a.x) < fabs(b.x));
49 }
50
51 inline void convex_hull(int &cnt, int n)
52 {
53 sort(data, data+n, cmp1);
54 start = data[0];
55 sort(data+1, data+n, cmp2);
56 convex[cnt++] = start;
57 convex[cnt++] = data[1];
58 for (int j(2); j<n; ++j) {
59 while (cnt >= 2 && cross(convex[cnt-2],convex[cnt-1],convex[cnt-1],data[j]) <= 0)--cnt;//共线的话也应该弹出原来栈中的点
60 convex[cnt++] = data[j];
61 }
62 }
63
64 inline double get_circum(int cnt)
65 {
66 double circum = 0;
67 for (int i(0); i<cnt; ++i) {
68 circum += p_distance(convex[i],convex[(i+1)%cnt]);
69 }
70 return circum;
71 }
72
73 inline void get_tree(int data)
74 {
75 printf("Cut these trees:");
76 for (int i(0); data != 0; ++i,data >>= 1) {
77 if (data%2 == 1) {
78 printf(" %d",i+1);
79 }
80 }
81 }
82
83 inline int enum_tree(int n, double &end_circum)
84 {
85 double circum = 0;
86 int result = 0;
87 int bound = (1<<n) - 1;
88 int min_value = INT_MAX;
89 int min_tree = INT_MAX;
90 for (int i(1); i<bound; ++i) {
91 int j = 0;
92 int temp = i;
93 int tree_num = 0;
94 int value = 0;
95 double length = 0;
96 for (int cnt(0); cnt<T; ++cnt,temp >>= 1) {
97 if (temp != 0 && temp%2 == 1) {
98 value += tree[cnt].value;
99 length += tree[cnt].length;
100 ++tree_num;
101 } else data[j++] = tree[cnt];
102 }
103 if (value > min_value)continue;
104 if (j >= 2) {
105 int top = 0;
106 convex_hull(top,j);
107 circum = get_circum(top);
108 } else {
109 circum = 0;
110 }
111 if (length >= circum) {
112 if (value == min_value) {
113 if (tree_num < min_tree) {
114 min_tree= tree_num;
115 result = i;
116 end_circum = circum;
117 }
118 } else {
119 if (value < min_value) {
120 min_value = value;
121 min_tree = tree_num;
122 result = i;
123 end_circum = circum;
124 }
125 }
126 }
127 }
128 return result;
129 }
130
131 inline double length(int n)
132 {
133 double len = 0;
134 for (int i(0); n != 0; ++i,n >>= 1) {
135 if (n%2 == 1) {
136 len += tree[i].length;
137 }
138 }
139 return len;
140 }
141
142 int main()
143 {
144 int count = 1;
145 while (scanf("%d",&T) && T != 0) {
146 for (int i(0); i<T; ++i) {
147 scanf("%lf%lf%d%lf",&tree[i].x,&tree[i].y,&tree[i].value,&tree[i].length);
148 }
149 double circum = 0;
150 int result = enum_tree(T,circum);
151 printf("Forest %d\n",count++);
152 get_tree(result);
153 printf("\nExtra wood: %.2lf\n\n",length(result) - circum);
154 }
155 return 0;
156 }



你可能感兴趣的:(poj)