1、LA 5908/UVA1517 Tracking RFIDs
题意:给出s个传感器的位置,以及其感应范围。如果某个方向上有墙,则该方向上感应距离减1.现在有w个墙,给出p个物品的位置,问其能被几个传感器探测到。
思路:传感器用set保存。之后传感器和物品之间是否有墙用线段是否相交来判断。
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<set> 5 #include<cmath> 6 using namespace std; 7 typedef long long ll; 8 const double eps = 1e-6; 9 10 struct point 11 { 12 int x, y; 13 point(int xx=0, int yy=0):x(xx),y(yy){ } 14 friend bool operator < (const point& a,const point& b) 15 { 16 return (a.x != b.x) ? a.x < b.x : a.y < b.y; 17 } 18 }; 19 struct line 20 { 21 int x; 22 int y; 23 line(int xx=0,int yy=0):x(xx),y(yy){ } 24 }; 25 26 line operator - (point a, point b) 27 {//得到点a和点b形成的直线的方向向量 28 return line(a.x - b.x, a.y - b.y); 29 } 30 int cross(line a, line b) 31 {//返回0则两条直线平行,否则,直线相交:大于0说明b.y/b.x>a.y/a.x,b的斜率大 32 return a.x * b.y - b.x * a.y; 33 } 34 double dis(point a, point b) 35 {//两点之间的直线距离 36 return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); 37 } 38 39 int direction(point p1, point p2, point p3) 40 {//判断点p3在直线p1-p2上还是在其两侧,上侧为负,下侧为正,在直线上为0 41 return cross(p3 - p1, p2 - p1); 42 } 43 44 //判断点np是否在线段p1-p2 45 bool on_segment(point p1, point p2, point np) 46 { 47 if (np.x < min(p1.x, p2.x)) return false; 48 if (np.x > max(p1.x, p2.x)) return false; 49 if (np.y < min(p1.y, p2.y)) return false; 50 if (np.y > max(p1.y, p2.y)) return false; 51 return true; 52 } 53 54 //判断线段p1-p2和p3-p4是否相交 55 bool segment_intersect(point p1, point p2, point p3, point p4) 56 { 57 // 必须用 long long 58 ll d1 = direction(p1, p2, p3); 59 ll d2 = direction(p1, p2, p4); 60 ll d3 = direction(p3, p4, p1); 61 ll d4 = direction(p3, p4, p2); 62 63 if (d1 * d2 < 0 && d3 * d4 < 0) return true;//p1、p2分别在线段p3-p4两侧,并且p3、p4分别在线段p1-p2两侧则说明两条线段相交 64 if (d1 == 0 && on_segment(p1, p2, p3)) return true; 65 if (d2 == 0 && on_segment(p1, p2, p4)) return true; 66 if (d3 == 0 && on_segment(p3, p4, p1)) return true; 67 if (d4 == 0 && on_segment(p3, p4, p2)) return true; 68 return false; 69 } 70 71 set<int> sensors[20005];//传感器坐标 72 set<int>::iterator it; 73 point wall_l[15], wall_r[15];//墙的起止点坐标 74 75 int main() 76 { 77 int T; 78 scanf("%d", &T); 79 80 while (T--) 81 { 82 for (int i = 0; i < 20005; i++) 83 sensors[i].clear(); 84 85 int s, r, w, p; 86 scanf("%d%d%d%d", &s, &r, &w, &p); 87 88 for (int i = 0; i < s; i++) 89 { 90 int x, y; 91 scanf("%d%d", &x, &y); 92 sensors[x + 10000].insert(y);//注意x为负数处理 93 } 94 95 for (int i = 0; i < w; i++) 96 scanf("%d%d%d%d", &wall_l[i].x, &wall_l[i].y, &wall_r[i].x, &wall_r[i].y); 97 98 while (p--) 99 { 100 point p1; 101 scanf("%d%d", &p1.x, &p1.y); 102 103 vector<point> ans; 104 for (int i = -r; i <= r; i++) 105 {//枚举x差值 106 int x = p1.x + i; 107 int y = ceil(p1.y - sqrt(r*r - (p1.x - x)*(p1.x - x)));//确定当前x坐标y可取下限 108 int k = x + 10000; 109 if (k < 0 || k > 20000) continue; 110 it = sensors[k].lower_bound(y); 111 while (it != sensors[k].end()) 112 {//传感器的横坐标为x,从当前y值增加 113 point p2(x, *it++);//当前可取传感器 114 double d = dis(p1, p2); 115 if (d > r + eps) break; 116 117 double add = 0; 118 for (int k = 0; k < w; k++)//判断是否有墙在两点之间 119 if (segment_intersect(p1, p2, wall_l[k], wall_r[k])) add++; 120 121 if (d + add < r + eps) ans.push_back(p2); 122 } 123 } 124 sort(ans.begin(), ans.end()); 125 printf("%d", ans.size()); 126 for (int i = 0; i < ans.size(); i++) 127 printf(" (%d,%d)", ans[i].x, ans[i].y); 128 printf(" "); 129 } 130 } 131 return 0; 132 }
2、 LA 3634/UVA 12096 The SetStack Computer
题意:模拟集合栈。
思路:给每一个不同集合映射一个编号。
1 #include <iostream> 2 #include <set> 3 #include <map> 4 #include <vector> 5 #include <stack> 6 #include <algorithm> 7 #include<iterator> 8 using namespace std; 9 10 map<set<int>, int> id; 11 map<set<int>, int>::iterator it; 12 vector<set<int> > v; 13 char op[15]; 14 int getID(set<int> x) 15 { 16 it = id.find(x); 17 if (it != id.end()) 18 return it->second; 19 v.push_back(x); 20 return id[x] = v.size() - 1; 21 } 22 23 int main() 24 { 25 int T, n; 26 scanf("%d", &T); 27 while (T--) 28 { 29 scanf("%d", &n); 30 id.clear(); 31 v.clear(); 32 stack<int> s; 33 while (n--) 34 { 35 scanf("%s", op); 36 if (op[0] == 'P') 37 s.push(getID(set<int>())); 38 else if (op[0] == 'D') 39 s.push(s.top()); 40 else 41 { 42 set<int> t1 = v[s.top()]; s.pop(); 43 set<int> t2 = v[s.top()]; s.pop(); 44 set<int> t; 45 if (op[0] == 'U') 46 { 47 set_union(t1.begin(), t1.end(), t2.begin(), t2.end(), inserter(t, t.begin())); 48 s.push(getID(t)); 49 } 50 else if (op[0] == 'I') 51 { 52 set_intersection(t1.begin(), t1.end(), t2.begin(), t2.end(), inserter(t, t.begin())); 53 s.push(getID(t)); 54 } 55 else if (op[0] == 'A') 56 { 57 t2.insert(getID(t1)); 58 s.push(getID(t2)); 59 } 60 } 61 printf("%d ",v[s.top()].size()); 62 } 63 printf("*** "); 64 } 65 return 0; 66 }