zoukankan      html  css  js  c++  java
  • STL之map、set灵活使用

    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 }
    View Code

     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 }
    View Code
  • 相关阅读:
    python input函数
    linux可用内存判断
    python if-elif-else 判断
    python if判断
    python使用range()函数创建数字列表list
    python range函数
    python语法缩进
    python for循环
    python列表删除和排序
    hbctf 父亲的信
  • 原文地址:https://www.cnblogs.com/ivan-count/p/7448202.html
Copyright © 2011-2022 走看看