ABC题意及解法见课件。这里附上代码。
A:POJ 2318

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <iomanip> 16 #include <cctype> 17 #include <cassert> 18 #include <bitset> 19 #include <ctime> 20 21 using namespace std; 22 23 #define pau system("pause") 24 #define ll long long 25 #define pii pair<int, int> 26 #define pb push_back 27 #define mp make_pair 28 #define clr(a, x) memset(a, x, sizeof(a)) 29 30 const double pi = acos(-1.0); 31 const int INF = 0x3f3f3f3f; 32 const int MOD = 1e9 + 7; 33 const double EPS = 1e-9; 34 35 struct point { 36 int x, y; 37 point () {} 38 point (int x, int y) : x(x), y(y) {} 39 void input() { 40 scanf("%d%d", &x, &y); 41 } 42 }; 43 struct segment { 44 point p1, p2; 45 segment () {} 46 segment (point p1, point p2) : p1(p1), p2(p2) {} 47 void input() { 48 p1.input(); 49 p2.input(); 50 } 51 } seg[5015]; 52 double cross_mul(point p1, point p2, point p3) { 53 return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y); 54 } 55 bool ok(segment s, point p) { 56 return cross_mul(s.p1, s.p2, p) < 0; 57 } 58 int n, m, x_left, x_right, y_up, y_down, is_first = 1, cnt[5015]; 59 int main() { 60 while (~scanf("%d", &n) && n) { 61 scanf("%d%d%d%d%d", &m, &x_left, &y_up, &x_right, &y_down); 62 seg[0] = segment(point(x_left, y_down), point(x_left, y_up)); 63 for (int i = 1; i <= n; ++i) { 64 int u, l; 65 scanf("%d%d", &u, &l); 66 seg[i] = segment(point(l, y_down), point(u, y_up)); 67 } 68 clr(cnt, 0); 69 for (int i = 1; i <= m; ++i) { 70 int x, y; 71 scanf("%d%d", &x, &y); 72 int l = 0, r = n, mi, res; 73 while (l <= r) { 74 mi = l + r >> 1; 75 if (ok(seg[mi], point(x, y))) { 76 l = (res = mi) + 1; 77 } else { 78 r = mi - 1; 79 } 80 } 81 ++cnt[res]; 82 } 83 if (is_first) { 84 is_first = 0; 85 } else { 86 puts(""); 87 } 88 for (int i = 0; i <= n; ++i) { 89 printf("%d: %d ", i, cnt[i]); 90 } 91 } 92 return 0; 93 }
B: POJ 3304

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <iomanip> 16 #include <cctype> 17 #include <cassert> 18 #include <bitset> 19 #include <ctime> 20 21 using namespace std; 22 23 #define pau system("pause") 24 #define ll long long 25 #define pii pair<int, int> 26 #define pb push_back 27 #define mp make_pair 28 #define clr(a, x) memset(a, x, sizeof(a)) 29 30 const double pi = acos(-1.0); 31 const int INF = 0x3f3f3f3f; 32 const int MOD = 1e9 + 7; 33 const double EPS = 1e-8; 34 35 int T, n; 36 struct point { 37 double x, y; 38 point () {} 39 point (double x, double y) : x(x), y(y) {} 40 void input() { 41 scanf("%lf%lf", &x, &y); 42 } 43 double dis(point p) { 44 return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); 45 } 46 }; 47 struct seg { 48 point p1, p2; 49 seg () {} 50 seg (point p1, point p2) : p1(p1), p2(p2) {} 51 void input() { 52 p1.input(); 53 p2.input(); 54 } 55 } s[105]; 56 double cross_mul(point p1, point p2, point p3) { 57 return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y); 58 } 59 bool cross(point pa, point pb, seg l) { 60 point p1 = l.p1, p2 = l.p2; 61 return cross_mul(pa, pb, p1) * cross_mul(pa, pb, p2) <= EPS; 62 } 63 bool solve(point p1, point p2) { 64 if (p1.dis(p2) <= EPS) return false; 65 for (int i = 1; i <= n; ++i) { 66 if (!cross(p1, p2, s[i])) { 67 return false; 68 } 69 } 70 return true; 71 } 72 int main() { 73 scanf("%d", &T); 74 while (T--) { 75 scanf("%d", &n); 76 for (int i = 1; i <= n; ++i) { 77 s[i].input(); 78 } 79 bool ans = 0; 80 if (1 == n) ans = 1; 81 for (int i = 1; i < n; ++i) { 82 point p1 = s[i].p1, p2 = s[i].p2; 83 for (int j = i + 1; j <= n; ++j) { 84 point p3 = s[j].p1, p4 = s[j].p2; 85 if (solve(p1, p3) || solve(p1, p4) || solve(p2, p3) || solve(p2, p4)) { 86 ans = 1; 87 } 88 } 89 } 90 puts(ans ? "Yes!" : "No!"); 91 } 92 return 0; 93 }
C: POJ 1127

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <iomanip> 16 #include <cctype> 17 #include <cassert> 18 #include <bitset> 19 #include <ctime> 20 21 using namespace std; 22 23 #define pau system("pause") 24 #define ll long long 25 #define pii pair<int, int> 26 #define pb push_back 27 #define mp make_pair 28 #define clr(a, x) memset(a, x, sizeof(a)) 29 30 const double pi = acos(-1.0); 31 const int INF = 0x3f3f3f3f; 32 const int MOD = 1e9 + 7; 33 const double EPS = 1e-6; 34 35 struct point { 36 int x, y; 37 point () {} 38 point (int x, int y) : x(x), y(y) {} 39 point operator - (const point &p) const { 40 return point(x - p.x, y - p.y);} 41 }; 42 struct seg { 43 point p1, p2; 44 seg () {} 45 seg (point p1, point p2) : p1(p1), p2(p2) {} 46 }; 47 int cross_mul(point p1, point p2) { 48 return p1.x * p2.y - p1.y * p2.x; 49 } 50 bool between(point a, point b, point c) {// a between b and c 51 return (a.x - b.x) * (a.x - c.x) <= 0 && (a.y - b.y) * (a.y - c.y) <= 0; 52 } 53 bool cross(seg l1, seg l2) { 54 int res1 = cross_mul(l1.p2 - l1.p1, l2.p1 - l1.p1); 55 int res2 = cross_mul(l1.p2 - l1.p1, l2.p2 - l1.p1); 56 int res3 = cross_mul(l2.p2 - l2.p1, l1.p1 - l2.p1); 57 int res4 = cross_mul(l2.p2 - l2.p1, l1.p2 - l2.p1); 58 if (!(res1 | res2 | res3 | res4)) { 59 return between(l1.p1, l2.p1, l2.p2) || between(l1.p2, l2.p1, l2.p2) || 60 between(l2.p1, l1.p1, l1.p2) || between(l2.p2, l1.p1, l1.p2); 61 } 62 return res1 * res2 <= 0 && res3 * res4 <= 0; 63 } 64 int Rank[15], parent[15], n; 65 void ini() { 66 for (int i = 1; i <= n; ++i) { 67 Rank[i] = 1; 68 parent[i] = i; 69 } 70 } 71 int Find(int x) {return x == parent[x] ? x : parent[x] = Find(parent[x]);} 72 void uni(int x, int y) { 73 x = Find(x), y = Find(y); 74 if (x == y) return; 75 76 if (Rank[x] < Rank[y]) { 77 parent[x] = y; 78 } else { 79 parent[y] = x; 80 if (Rank[x] == Rank[y]) ++Rank[x]; 81 } 82 } 83 seg s[15]; 84 int main() { 85 while (~scanf("%d", &n) && n) { 86 for (int i = 1; i <= n; ++i) { 87 scanf("%d%d%d%d", &s[i].p1.x, &s[i].p1.y, &s[i].p2.x, &s[i].p2.y); 88 } 89 ini(); 90 for (int i = 1; i <= n; ++i) { 91 for (int j = i + 1; j <= n; ++j) { 92 if (cross(s[i], s[j])) uni(i, j); 93 } 94 } 95 int x, y; 96 while (~scanf("%d%d", &x, &y) && x && y) { 97 puts(Find(x) == Find(y) ? "CONNECTED" : "NOT CONNECTED"); 98 } 99 } 100 return 0; 101 }
D: POJ 1696
题意:
一只蚂蚁只能向左走或直走,且不能经过之前走过的路径,问路径最多能覆盖多少个点。
思路:
每次选择蚂蚁左边未走过的最靠右的点。实际上,未走过的点永远在蚂蚁的左边;且蚂蚁的路径不会和之前有交点。这两条性质都可以类数学归纳法证明。这样便会遍历到所有的点。
因此,每次贪心选以上一个位置为极点,极角最小的点。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 struct Point { 45 int x, y; 46 Point () {} 47 Point (int x, int y) : x(x), y(y) {} 48 ll operator ^ (const Point &p) const { 49 return x * p.y - y * p.x; 50 } 51 Point operator - (const Point &p) const { 52 return Point(x - p.x, y - p.y); 53 } 54 bool operator == (const Point &p) const { 55 return x == p.x && y == p.y; 56 } 57 bool operator < (const Point &p) const { 58 return y == p.y ? x < p.x : y < p.y; 59 } 60 void input() { 61 scanf("%d", &x); 62 scanf("%d%d", &x, &y); 63 } 64 void output() { 65 printf("%d %d ", x, y); 66 } 67 double dis(const Point &p) const { 68 return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); 69 } 70 } p[1015], pp; 71 bool cmp(const Point &p1, const Point &p2) { 72 ll v = (p1 - pp) ^ (p2 - pp); 73 if (v) return v > 0; 74 return abs(p1.x - pp.x) + abs(p1.y - pp.y) < abs(p2.x - pp.x) + abs(p2.y - pp.y); 75 } 76 int cross(Point pp, Point p1, Point p2) { 77 return ((p1 - pp) ^ (p2 - pp)) > 0; 78 } 79 int T, n, vis[55]; 80 vector<int> vec; 81 int main() { 82 scanf("%d", &T); 83 while (T--) { 84 scanf("%d", &n); 85 for (int i = 1; i <= n; ++i) { 86 p[i].input(); 87 vis[i] = 0; 88 } 89 pp = p[1]; int id = 1; 90 for (int i = 2; i <= n; ++i) { 91 if (p[i] < pp) { 92 pp = p[i]; 93 id = i; 94 } 95 } 96 vec.clear(); 97 vis[id] = 1; vec.pb(id); 98 for (int i = 1; i < n; ++i) { 99 int j = 1; 100 for (; j <= n; ++j) { 101 if (!vis[j]) { 102 id = j; 103 break; 104 } 105 } 106 for (++j; j <= n; ++j) { 107 if (vis[j]) continue; 108 if (cmp(p[j], p[id])) { 109 id = j; 110 } 111 } 112 vis[id] = 1; vec.pb(id); 113 pp = p[id]; 114 } 115 printf("%d", n); 116 for (int i = 0; i < vec.size(); ++i) { 117 printf(" %d", vec[i]); 118 } 119 puts(""); 120 } 121 return 0; 122 }
E: HDU 1705
题意:对一个整点三角形,问内部有多少整点。
思路:求出面积S,对于边(x1, y1), (x2, y2),其上的整点数为gcd(abs(x1 - x2), abs(y1 - y2))。如此累计便得出边上整点数s。 n = S - s / 2 + 1.

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 int x[3], y[3]; 45 int main() { 46 while (1) { 47 int flag = 0; 48 for (int i = 0; i < 3; ++i) { 49 scanf("%d%d", &x[i], &y[i]); 50 if (x[i] || y[i]) flag = 1; 51 } 52 if (!flag) break; 53 int S = abs((x[1] - x[0]) * (y[2] - y[0]) - (x[2] - x[0]) * (y[1] - y[0])) / 2; 54 ll s = 0; 55 for (int i = 0; i < 3; ++i) { 56 s += __gcd(abs(x[(i + 1) % 3] - x[i]), abs(y[(i + 1) % 3] - y[i])); 57 } 58 printf("%d ", S + 1 - s / 2); 59 } 60 return 0; 61 }
F: HDU 1756
题意: 判断一个点是否在多边形内部。
思路:先判断是否在边上。再点射法求出水平射线与下降端点和边的相交次数和。为奇数在内部,为偶数在外部。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 int n, m; 45 struct Point { 46 int x, y, cnt_down; 47 Point () {} 48 Point (int _x, int _y) { 49 x = _x, y = _y, cnt_down = 0; 50 } 51 Point operator - (const Point &p) const { 52 return Point(x - p.x, y - p.y); 53 } 54 ll operator ^ (const Point &p) const { 55 return x * p.y - y * p.x; 56 } 57 void input() { 58 scanf("%d%d", &x, &y); 59 cnt_down = 0; 60 } 61 } p[105]; 62 struct Seg { 63 Point s, e; 64 Seg () {} 65 Seg (Point s, Point e) : s(s), e(e) {} 66 bool cross(const Seg &seg) const { 67 return ((s - seg.s) ^ (seg.e - seg.s)) * ((e - seg.s) ^ (seg.e - seg.s)) < 0; 68 } 69 }; 70 bool between(Point p, Seg seg) { 71 if ((p - seg.s) ^ (seg.e - seg.s)) return false; 72 return (p.x - seg.s.x) * (p.x - seg.e.x) <= 0 && (p.y - seg.s.y) * (p.y - seg.e.y) <= 0; 73 } 74 int main() { 75 while (~scanf("%d", &n)) { 76 for (int i = 1; i <= n; ++i) { 77 p[i].input(); 78 } 79 for (int i = 1; i <= n; ++i) { 80 int j = i % n + 1; 81 if (p[i].y < p[j].y) ++p[i].cnt_down; 82 else if (p[j].y < p[i].y) ++p[j].cnt_down; 83 } 84 scanf("%d", &m); 85 while (m--) { 86 Point pp; pp.input(); 87 int f = 0; 88 for (int i = 1; i <= n; ++i) { 89 if (between(pp, Seg(p[i], p[i % n + 1]))) { 90 f = 1; 91 break; 92 } 93 } 94 if (f) { 95 puts("Yes"); 96 continue; 97 } 98 Seg ss = Seg(pp, Point(1001, pp.y)); 99 int cnt = 0; 100 for (int i = 1; i <= n; ++i) { 101 if (between(p[i], ss)) cnt += p[i].cnt_down; 102 } 103 for (int i = 1; i <= n; ++i) { 104 if (ss.cross(Seg(p[i], p[i % n + 1])) && Seg(p[i], p[i % n + 1]).cross(ss)) ++cnt; 105 } 106 puts(cnt & 1 ? "Yes" : "No"); 107 } 108 } 109 return 0; 110 }
G: POJ 1556
题意:矩形内n组墙,每组墙由中间两块空隙构成。问从起点到终点不撞墙的最短距离。
思路:最短路径的所有线段端点一定都是原来墙的端点。于是对于第i组墙的第j个点,枚举所有转移到他上的端点,判断两点连线是否撞墙。如不撞墙,更新dp值。最终dp[n + 1][1]即为所求。
复杂度O(n^3).

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 struct Point { 45 double x, y; 46 Point () {} 47 Point (double x, double y) : x(x), y(y) {} 48 double operator ^ (const Point &p) const { 49 return x * p.y - y * p.x; 50 } 51 Point operator - (const Point &p) const { 52 return Point(x - p.x, y - p.y); 53 } 54 bool operator == (const Point &p) const { 55 return x == p.x && y == p.y; 56 } 57 bool operator < (const Point &p) const { 58 return y == p.y ? x < p.x : y < p.y; 59 } 60 void input() { 61 scanf("%d", &x); 62 scanf("%d%d", &x, &y); 63 } 64 void output() { 65 printf("%d %d ", x, y); 66 } 67 double dis(const Point &p) const { 68 return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); 69 } 70 } p[13][5], pp; 71 bool cmp(const Point &p1, const Point &p2) { 72 ll v = (p1 - pp) ^ (p2 - pp); 73 if (v) return v > 0; 74 return abs(p1.x - pp.x) + abs(p1.y - pp.y) < abs(p2.x - pp.x) + abs(p2.y - pp.y); 75 } 76 int cross(Point pp, Point p1, Point p2) { 77 return ((p1 - pp) ^ (p2 - pp)) > EPS; 78 } 79 struct Seg { 80 Point s, e; 81 Seg () {} 82 Seg (Point s, Point e) : s(s), e(e) {} 83 bool cross(Point p1, Point p2) { 84 return ((p2 - p1) ^ (s - p1)) * ((p2 - p1) ^ (e - p1)) < EPS; 85 } 86 } ss[23][5]; 87 bool cross_Seg(Seg s1, Seg s2) { 88 return s1.cross(s2.s, s2.e) && s2.cross(s1.s, s1.e); 89 } 90 int n, cnt[23]; 91 double dp[23][5]; 92 int main() { 93 while (~scanf("%d", &n) && ~n) { 94 for (int i = 1; i <= n; ++i) { 95 double x, y; 96 scanf("%lf", &x); 97 for (int j = 1; j <= 4; ++j) { 98 scanf("%lf", &y); 99 p[i][j] = Point(x, y); 100 } 101 cnt[i] = 4; 102 ss[i][1] = Seg(Point(x, 0), p[i][1]); 103 ss[i][2] = Seg(p[i][2], p[i][3]); 104 ss[i][3] = Seg(p[i][4], Point(x, 10)); 105 } 106 cnt[0] = cnt[n + 1] = 1; 107 p[0][1] = Point(0, 5); 108 p[n + 1][1] = Point(10, 5); 109 dp[0][1] = 0; 110 for (int i = 1; i <= n + 1; ++i) { 111 for (int j = 1; j <= cnt[i]; ++j) { 112 dp[i][j] = INF; 113 } 114 } 115 for (int i = 1; i <= n + 1; ++i) { 116 for (int j = 1; j <= cnt[i]; ++j) { 117 for (int k = 0; k < i; ++k) { 118 for (int l = 1; l <= cnt[k]; ++l) { 119 Seg ts = Seg(p[i][j], p[k][l]); 120 int f = 1; 121 for (int o = k + 1; o < i; ++o) { 122 for (int _ = 1; _ <= 3; ++_) { 123 if (cross_Seg(ts, ss[o][_])) { 124 f = 0; 125 break; 126 } 127 } 128 } 129 if (f) { 130 dp[i][j] = min(dp[i][j], dp[k][l] + p[i][j].dis(p[k][l])); 131 } 132 } 133 } 134 } 135 } 136 printf("%.2f ", dp[n + 1][1]); 137 } 138 return 0; 139 }
H: POJ 1113
题意:对于一个多边形,要筑一个围墙,使多边形上每个点到墙的距离都不超过L。求围墙最短长度。
思路:实际距离就是凸包长度加上一个半径为l的圆的周长。套凸包板子即可。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 struct Point { 45 int x, y; 46 Point () {} 47 Point (int x, int y) : x(x), y(y) {} 48 ll operator ^ (const Point &p) const { 49 return x * p.y - y * p.x; 50 } 51 Point operator - (const Point &p) const { 52 return Point(x - p.x, y - p.y); 53 } 54 bool operator == (const Point &p) const { 55 return x == p.x && y == p.y; 56 } 57 bool operator < (const Point &p) const { 58 return y == p.y ? x < p.x : y < p.y; 59 } 60 void input() { 61 scanf("%d%d", &x, &y); 62 } 63 void output() { 64 printf("%d %d ", x, y); 65 } 66 double dis(const Point &p) const { 67 return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); 68 } 69 } p[1015], pp; 70 bool cmp(const Point &p1, const Point &p2) { 71 if (pp == p1) return true; 72 if (pp == p2) return false; 73 ll v = (p1 - pp) ^ (p2 - pp); 74 if (v) return v > 0; 75 return abs(p1.x - pp.x) + abs(p1.y - pp.y) < abs(p2.x - pp.x) + abs(p2.y - pp.y); 76 } 77 int n, l; 78 stack<Point> sta; 79 vector<Point> vec; 80 int main() { 81 scanf("%d%d", &n, &l); 82 for (int i = 1; i <= n; ++i) { 83 p[i].input(); 84 } 85 pp = p[1]; 86 for (int i = 2; i <= n; ++i) { 87 if (p[i] < pp) { 88 pp = p[i]; 89 } 90 } 91 sort(p + 1, p + n + 1, cmp); 92 sta.push(p[1]), sta.push(p[2]); 93 for (int i = 3; i <= n; ++i) { 94 while (sta.size() > 1) { 95 Point p1 = sta.top(); sta.pop(); 96 Point p2 = sta.top(); 97 if (((p[i] - p2) ^ (p1 - p2)) < 0) { 98 sta.push(p1); 99 break; 100 } 101 } 102 sta.push(p[i]); 103 } 104 while (sta.size()) { 105 vec.pb(sta.top()); sta.pop(); 106 } 107 for (int i = (int)vec.size() - 1; ~i; --i) { 108 //vec[i].output(); 109 } 110 double ans = 0; 111 for (int i = 0; i < vec.size(); ++i) { 112 int j = (i + 1) % vec.size(); 113 ans += vec[i].dis(vec[j]); 114 } 115 ans += 2 * pi * l; 116 printf("%.0f ", ans); 117 return 0; 118 }
I:POJ 2653
思路:注意到在顶部的线段小于1000.于是我们每次加入线段时,扫一遍所有在顶部的线段,如果相交,那他就不再是顶部了,从这个集合中删去。可以用链表维护这个东西。复杂度O(1000n)。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 struct point { 37 double x, y; 38 point () {} 39 point (double x, double y) : x(x), y(y) {} 40 void input() { 41 scanf("%lf%lf", &x, &y); 42 } 43 }; 44 struct segment { 45 point p1, p2; 46 segment () {} 47 segment (point p1, point p2) : p1(p1), p2(p2) {} 48 void input() { 49 p1.input(); 50 p2.input(); 51 } 52 } seg[100015]; 53 double cross_mul(point p1, point p2, point p3) { 54 return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y); 55 } 56 bool cross(segment s1, segment s2) { 57 return cross_mul(s1.p1, s1.p2, s2.p1) * cross_mul(s1.p1, s1.p2, s2.p2) <= EPS && 58 cross_mul(s2.p1, s2.p2, s1.p1) * cross_mul(s2.p1, s2.p2, s1.p2) <= EPS; 59 } 60 list<int> ans; 61 int n; 62 int main() { 63 while (~scanf("%d", &n) && n) { 64 ans.clear(); 65 for (int i = 1; i <= n; ++i) { 66 seg[i].input(); 67 for (list<int>::iterator it = ans.begin(); it != ans.end();) { 68 int x = *it; 69 if (cross(seg[x], seg[i])) { 70 ans.erase(it++); 71 } else { 72 ++it; 73 } 74 } 75 ans.pb(i); 76 } 77 printf("Top sticks:"); 78 for (list<int>::iterator it = ans.begin(); it != ans.end();) { 79 printf(" %d", *it); 80 putchar(++it == ans.end() ? '.' : ','); 81 } 82 puts(""); 83 } 84 return 0; 85 }
J:HDU 6325
题意:求字典序最小上凸包。
思路:选最左边的点,按x排序正常跑凸包的基础上注意两点:
位置相同的点直接取id小的
凸包上共线的点中间的点选或不选由线上的后继点的id大小决定。比较大小进行取舍。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 struct Point { 45 ll x, y; 46 int id; 47 Point () {} 48 Point (int x, int y) : x(x), y(y) {} 49 ll operator ^ (const Point &p) const { 50 return x * p.y - y * p.x; 51 } 52 Point operator - (const Point &p) const { 53 return Point(x - p.x, y - p.y); 54 } 55 bool operator == (const Point &p) const { 56 return x == p.x && y == p.y; 57 } 58 bool operator < (const Point &p) const { 59 return x == p.x ? id > p.id : x < p.x; 60 } 61 void input(int i) { 62 id = i; 63 scanf("%lld%lld", &x, &y); 64 } 65 void output() { 66 printf("%lld %lld ", x, y); 67 } 68 double dis(const Point &p) const { 69 return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); 70 } 71 } p[200015], pp; 72 ll cross(Point pp, Point p1, Point p2) { 73 return ((p1 - pp) ^ (p2 - pp)); 74 } 75 int T, n; 76 deque<int> que; 77 int main() { 78 scanf("%d", &T); 79 while (T--) { 80 scanf("%d", &n); 81 for (int i = 1; i <= n; ++i) { 82 p[i].input(i); 83 } 84 sort(p + 1, p + n + 1); 85 que.pb(1), que.pb(2); 86 for (int i = 3; i <= n; ++i) { 87 while (que.size() > 1) { 88 int x = que.back(); que.pop_back(); 89 if (p[x] == p[i]) continue; 90 int y = que.back(); 91 ll v = cross(p[y], p[i], p[x]); 92 if (v < 0) continue; 93 if (!v && p[i].id < p[x].id) continue; 94 que.pb(x); 95 break; 96 } 97 que.pb(i); 98 } 99 printf("1"); que.pop_front(); 100 while (que.size()) { 101 printf(" %d", p[que.front()].id); que.pop_front(); 102 } 103 puts(""); 104 } 105 return 0; 106 }
题意:平面上n个线,形成一坨交点,问多少个三角形外接圆经过圆心。
思路:等价于圆心向所有直线做垂足,问多少个三元垂足对共线。
额外注意double可能丢精度,用两个整数存有理数。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <iomanip> 16 #include <cctype> 17 #include <cassert> 18 #include <bitset> 19 #include <ctime> 20 21 using namespace std; 22 23 #define pau system("pause") 24 #define ll long long 25 #define pll pair<ll, ll> 26 #define pb push_back 27 #define mp make_pair 28 #define clr(a, x) memset(a, x, sizeof(a)) 29 30 const double pi = acos(-1.0); 31 const int INF = 0x3f3f3f3f; 32 const int MOD = 1e9 + 7; 33 const double EPS = 1e-9; 34 35 int n, a[2015], b[2015], c[2015]; 36 ll px[2015], qx[2015], py[2015], qy[2015], rx, ry; 37 ll gcd(ll x, ll y) {while (y) y ^= x ^= y ^= x %= y; return x;} 38 int flag; 39 map<pll, int> mmp; 40 ll ans = 0; 41 int main() { 42 scanf("%d", &n); 43 for (int i = 1; i <= n; ++i) { 44 scanf("%d%d%d", &a[i], &b[i], &c[i]); 45 if (!c[i]) ++flag; 46 px[i] = (ll)a[i] * c[i], py[i] = (ll)b[i] * c[i]; 47 qx[i] = qy[i] = (ll)a[i] * a[i] + (ll)b[i] * b[i]; 48 } 49 for (int i = 1; i <= n; ++i) { 50 if (!c[i]) continue; 51 mmp.clear(); 52 for (int j = 1; j < i; ++j) { 53 if (!c[j]) continue; 54 rx = px[i] * qx[j] - px[j] * qx[i]; 55 ry = py[i] * qy[j] - py[j] * qy[i]; 56 ll g = gcd(rx, ry); 57 //printf("rx = %lld, ry = %lld, g = %lld ", rx, ry, g); 58 rx /= g, ry /= g; 59 if (rx < 0 || !rx && ry < 0) { 60 rx = -rx; 61 ry = -ry; 62 } 63 ++mmp[pll(rx, ry)]; 64 } 65 for (map<pll, int>::iterator it = mmp.begin(); it != mmp.end(); ++it) { 66 ll x = (*it).second; 67 ans += x * (x - 1) >> 1; 68 } 69 } 70 if (2 == flag) ans += n - 2; 71 printf("%I64d ", ans); 72 return 0; 73 }
题意:先不说了...
思路:我们只需维护重心位置以及每个点相对重心的关系。然后每次操作暴力模拟。码量较大。

1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const long double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const long double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T; 42 */ 43 44 int n, q; 45 struct point { 46 long double x, y; 47 point() {} 48 point (long double x, long double y) : x(x), y(y) {} 49 void input() { 50 //scanf("%lf%lf", &x, &y); 51 cin >> x >> y; 52 } 53 void output() { 54 double tx = x, ty = y; 55 printf("%.12f %.12f ", tx, ty); 56 } 57 point operator - (const point &p) const { 58 return point(x - p.x, y - p.y); 59 } 60 point operator + (const point &p) const { 61 return point(x + p.x, y + p.y); 62 } 63 long double operator ^ (const point &p) const { 64 return x * p.y - y * p.x; 65 } 66 point operator / (const long double &k) const { 67 return point(x / k, y / k); 68 } 69 point operator * (const long double &k) const { 70 return point(x * k, y * k); 71 } 72 long double dis(const point &p) const { 73 return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y)); 74 } 75 } p[100015]; 76 long double d0[100015], d1[100015], th[100015]; 77 long double cal_th(point p1, point p0, point p2) { 78 long double th1 = atan2(p1.y - p0.y, p1.x - p0.x); 79 long double th2 = atan2(p2.y - p0.y, p2.x - p0.x); 80 long double res = th1 - th2; 81 if (res < 0) res += 2 * pi; 82 return res; 83 } 84 multiset<int> rem; 85 point get_pos(int index) { 86 long double th1 = atan2(p[1].y - p[0].y, p[1].x - p[0].x); 87 long double th2 = th1 - th[index]; 88 if (th2 < 0) th2 += 2 * pi; 89 return p[0] + point(d0[index] * cos(th2), d0[index] * sin(th2)); 90 } 91 void rot_and_update(int index2) { 92 point p2 = get_pos(index2); 93 long double th01 = atan2(p[0].y - p2.y, p[0].x - p2.x); 94 long double th02 = 3 * pi / 2; 95 long double th0 = th02 - th01; 96 if (th0 < 0) th0 += 2 * pi; 97 long double th11 = atan2(p[1].y - p2.y, p[1].x - p2.x); 98 //p[0].output(), p[1].output(), p2.output(); 99 long double th12 = th11 + th0; 100 if (2 * pi <= th12) th12 -= 2 * pi; 101 //printf("index2 = %d ", index2); 102 p[0] = point(p2.x, p2.y - d0[index2]); 103 p[1] = p2 + point(d1[index2] * cos(th12), d1[index2] * sin(th12)); 104 } 105 void get_wp() { 106 long double s = 0; 107 p[0] = point(0, 0); 108 for (int i = 2; i < n; ++i) { 109 long double ts = (p[i] - p[1]) ^ (p[i] - p[i + 1]); 110 p[0] = p[0] + (p[1] + p[i] + p[i + 1]) / 3 * ts; 111 s += ts; 112 } 113 p[0] = p[0] / s; 114 } 115 int main() { 116 scanf("%d%d", &n, &q); 117 p[0] = point(0, 0); 118 for (int i = 1; i <= n; ++i) { 119 p[i].input(); 120 } 121 get_wp(); 122 for (int i = 1; i <= n; ++i) { 123 th[i] = cal_th(p[1], p[0], p[i]); 124 d0[i] = p[0].dis(p[i]); 125 d1[i] = p[1].dis(p[i]); 126 } 127 rem.insert(1), rem.insert(2); 128 while (q--) { 129 int op; 130 scanf("%d", &op); 131 if (1 == op) { 132 int f, t; 133 scanf("%d%d", &f, &t); 134 multiset<int>::iterator it = rem.lower_bound(f); 135 rem.erase(it); 136 int v = *rem.begin(); 137 rot_and_update(v); 138 rem.insert(t); 139 } else { 140 int v; 141 scanf("%d", &v); 142 get_pos(v).output(); 143 } 144 } 145 return 0; 146 } 147 /* 148 10 10 149 0 -100000000 150 1 -100000000 151 1566 -99999999 152 2088 -99999997 153 2610 -99999994 154 3132 -99999990 155 3654 -99999985 156 4176 -99999979 157 4698 -99999972 158 5220 -99999964 159 1 2 5 160 2 1 161 1 1 7 162 2 5 163 1 5 4 164 1 4 2 165 2 8 166 1 7 9 167 2 1 168 1 2 10 169 */