NWERC 2015 Problem H: Hole in One
Posted HITLJR
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NWERC 2015 Problem H: Hole in One相关的知识,希望对你有一定的参考价值。
暴力计算几何。。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const double eps = 1e-10; 4 inline int sgn(double x) 5 { 6 if (fabs(x) < eps) 7 return 0; 8 if (x < 0) 9 return -1; 10 return 1; 11 } 12 struct Point 13 { 14 double x, y; 15 Point() {} 16 Point(double x, double y): x(x), y(y) {} 17 void input() 18 { 19 scanf("%lf%lf", &x, &y); 20 } 21 double operator^(const Point &b)const 22 { 23 return x * b.y - y * b.x; 24 } 25 double operator*(const Point &b)const 26 { 27 return x * b.x + y * b.y; 28 } 29 Point operator-(const Point &b)const 30 { 31 return Point(x - b.x, y - b.y); 32 } 33 } hole, a[15], b[15]; 34 struct Line 35 { 36 Point s, e; 37 Line() {} 38 Line(Point s, Point e): s(s), e(e) {} 39 int segcrossseg(Line v) 40 { 41 int d1 = sgn((e - s) ^ (v.s - s)); 42 int d2 = sgn((e - s) ^ (v.e-s)); 43 int d3 = sgn((v.e-v.s) ^ (s - v.s)); 44 int d4 = sgn((v.e-v.s) ^ (e - v.s)); 45 if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) 46 return 2; 47 return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) || 48 (d2 == 0 && sgn((v.e-s) * (v.e-e)) <= 0) || 49 (d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) || 50 (d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0); 51 } 52 } wall[15]; 53 int n; 54 vector<int> per; 55 int vis[15]; 56 inline bool gao() 57 { 58 memset(vis, 0, sizeof(vis)); 59 double xx = 0, yy = 0; 60 double nowx = 0, nowy = 0; 61 int flagx = 0, flagy = 0; 62 int bx = 0, by = 0; 63 /*判断反射方向,求反射长度*/ 64 for (int j = 0; j < (int)per.size(); ++j) 65 { 66 int id = per[j]; 67 /*讨论竖直水平*/ 68 if (sgn(wall[id].s.x - wall[id].e.x) == 0) 69 { 70 if (flagx == 0) 71 { 72 flagx = sgn(wall[id].s.x - nowx); 73 if (sgn(wall[id].s.x - nowx) == 0 ) return 0; 74 bx = flagx; 75 } 76 else 77 { 78 if (flagx == sgn(wall[id].s.x - nowx)) return 0; 79 if (sgn(wall[id].s.x - nowx) == 0 ) return 0; 80 flagx = -flagx; 81 } 82 xx += fabs(wall[id].s.x - nowx); 83 nowx = wall[id].s.x; 84 } 85 else if (sgn(wall[id].s.y - wall[id].e.y) == 0) 86 { 87 if (flagy == 0) 88 { 89 flagy = sgn(wall[id].s.y - nowy); 90 if (sgn(wall[id].s.y - nowy) == 0 ) return 0; 91 by = flagy; 92 } 93 else 94 { 95 if (flagy == sgn(wall[id].s.y - nowy)) return 0; 96 if (sgn(wall[id].s.y - nowy) == 0 ) return 0; 97 flagy = -flagy; 98 } 99 yy += fabs(wall[id].s.y - nowy); 100 nowy = wall[id].s.y; 101 } 102 } 103 /*判断最后一下方向*/ 104 if (bx == 0) bx = 1; 105 if (by == 0) by = 1; 106 // 默认右上角 107 xx += fabs(hole.x - nowx); 108 yy += fabs(hole.y - nowy); 109 if (sgn(hole.x - nowx) == flagx && flagx != 0) return 0; 110 if (sgn(hole.y - nowy) == flagy && flagy != 0) return 0; 111 // 回不到洞 112 /*遍历反射过程*/ 113 double tmp = yy / xx; 114 int tmpflag = 0; 115 if (sgn(xx) == 0) tmpflag = 1; 116 nowx = 0, nowy = 0; 117 for (int j = 0; j < (int)per.size(); ++j) 118 { 119 int id = per[j]; 120 if (sgn(wall[id].s.x - wall[id].e.x) == 0) 121 { 122 double tmpx = fabs(wall[id].s.x - nowx); 123 double zz; 124 if (tmpflag == 0)zz = tmpx * tmp * by; 125 else zz = 0; 126 Point pp(wall[id].s.x, nowy + zz); 127 Line ll(pp, Point(nowx, nowy)); 128 if (ll.segcrossseg(wall[id])) 129 { 130 vis[id] = 1; 131 for (int i = 0 ; i < n; i++) 132 { 133 if (vis[i]) continue; 134 if(ll.segcrossseg(wall[i])) return 0; 135 } 136 } 137 else return 0; 138 bx = -bx; 139 nowx = pp.x ; 140 nowy = pp.y; 141 } 142 else 143 { 144 double tmpy = fabs(wall[id].s.y - nowy); 145 double zz; 146 if (tmpflag == 0)zz = tmpy / tmp * bx; 147 else zz = 0; 148 Point pp(nowx + zz, wall[id].s.y); 149 Line ll(pp, Point(nowx, nowy)); 150 if (ll.segcrossseg(wall[id])) 151 { 152 vis[id] = 1; 153 for (int i = 0 ; i < n; i++) 154 { 155 if (vis[i]) continue; 156 if(ll.segcrossseg(wall[i])) return 0; 157 } 158 } 159 else return 0; 160 by = -by; 161 nowx = pp.x ; 162 nowy = pp.y; 163 } 164 } 165 /*最后一次相交*/ 166 double tmpx = fabs(hole.x - nowx); 167 double tmpy = fabs(hole.y - nowy); 168 double zz; 169 if (tmpflag == 0)zz = tmpx * tmp * by; 170 else zz = 0; 171 Point pp(hole.x, nowy + zz); 172 if (sgn(pp.y - (nowy + zz)) != 0) return 0; 173 Line ll(pp, Point(nowx, nowy)); 174 for (int i = 0 ; i < n; i++) 175 { 176 if (vis[i]) continue; 177 if(ll.segcrossseg(wall[i])) return 0; 178 } 179 return 1; 180 } 181 182 inline int solve(int mask) 183 { 184 per.clear(); 185 for (int i = 0; i < n; ++i) 186 if ((mask >> i) & 1) 187 per.push_back(i); 188 int ret = 0; 189 do 190 { 191 if (gao()) return per.size(); 192 } 193 while (next_permutation(per.begin(), per.end())); 194 return -1; 195 } 196 int main() 197 { 198 scanf("%d", &n); 199 hole.input(); 200 for (int i = 0; i < n; ++i) 201 { 202 a[i].input(); 203 b[i].input(); 204 } 205 if (sgn(hole.x) < 0) 206 { 207 for (int i = 0; i < n; ++i) 208 { 209 a[i].x = -a[i].x; 210 b[i].x = -b[i].x; 211 } 212 hole.x = -hole.x; 213 } 214 if (sgn(hole.y) < 0) 215 { 216 for (int i = 0; i < n; ++i) 217 { 218 a[i].y = -a[i].y; 219 b[i].y = -b[i].y; 220 } 221 hole.y = -hole.y; 222 } 223 for (int i = 0; i < n; ++i) 224 wall[i] = Line(a[i], b[i]); 225 int st = 1 << n, res = -1; 226 for (int i = 0; i < st; ++i) 227 res = max(res, solve(i)); 228 if (res == -1) puts("impossible"); 229 else printf("%d\n", res); 230 return 0; 231 }
以上是关于NWERC 2015 Problem H: Hole in One的主要内容,如果未能解决你的问题,请参考以下文章
NWERC2016-Problem A(Arranging Hat)
COGS——T 803. [USACO Hol10] 政党 || 1776: [Usaco2010 Hol]cowpol 奶牛政坛
bzoj 4428: [Nwerc2015]Debugging调试
bzoj 4430: [Nwerc2015]Guessing Camels赌骆驼