zoukankan      html  css  js  c++  java
  • hdu 4400 离散化+二分+BFS(暴搜剪枝还超时的时候可以借鉴一下)

    Mines

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1110    Accepted Submission(s): 280


    Problem Description
    Terrorists put some mines in a crowded square recently. The police evacuate all people in time before any mine explodes. Now the police want all the mines be ignited. The police will take many operations to do the job. In each operation, the police will ignite one mine. Every mine has its "power distance". When a mine explodes, any other mine within the power distance of the exploding mine will also explode. Please NOTE that the distance is Manhattan distance here.

    More specifically, we put the mines in the Cartesian coordinate system. Each mine has position (x,y) and power distance d.

    The police want you to write a program and calculate the result of each operation.
     
    Input
    There are several test cases.
    In each test case:
    Line 1: an integer N, indicating that there are N mines. All mines are numbered from 1 to N.
    Line 2…N+1: There are 3 integers in Line i+1 (i starts from 1). They are the i-th mine’s position (xi,yi) and its power distance di. There can be more than one mine in the same point.
    Line N+2: an integer M, representing the number of operations.
    Line N+3...N+M+2 : Each line represents an operation by an integer k meaning that in this operation, the k-th mine will be ignited. It is possible to ignite a mine which has already exploded, but it will have no effect.

    1<=M<=N<=100000,0<=xi,yi<=10^9,0<=di<=10^9

    Input ends with N=0.
     
    Output
    For each test case, you should print ‘Case #X:’ at first, which X is the case number starting from 1. Then you print M lines, each line has an integer representing the number of mines explode in the correspondent operation.
     
    Sample Input
    3
    0 0 0
    1 1 2
    2 2 2
    3
    1
    2
    3
    0
     
    Sample Output
    Case #1:
    1
    2
    0
      1 /*
      2 曼哈顿距离为两坐标的轴绝对值和即:abs(a.x-b.x)+abs(a.y-b.y)
      3 直接暴搜时间复杂度O(N*M)会超时
      4 对它进行优化剪枝,先对x值离散化,再通过二分查找范围,
      5 */
      6 #include <iostream>
      7 #include <cstdio>
      8 #include <cstring>
      9 #include <set>
     10 #include <queue>
     11 #include <cmath>
     12 #include <algorithm>
     13 using namespace std;
     14 
     15 const int maxn=100010;
     16 int N,M,X,f[maxn];
     17 bool vis[maxn];//标记数组
     18 
     19 struct Point
     20 {
     21     int x,y,d;//x坐标,y坐标,曼哈顿距离
     22 }p[maxn];
     23 
     24 Point read_point()
     25 {
     26     Point t;
     27     scanf("%d %d %d",&t.x,&t.y,&t.d);
     28     return t;
     29 }
     30 struct Mine
     31 {
     32     int y,n;//y坐标,编号
     33     Mine(){}
     34     Mine(int y=0,int n=0):y(y),n(n){}
     35     bool operator<(const Mine &A) const//对y重载小于号
     36     { 
     37         return y<A.y;
     38     }
     39 };
     40 multiset<Mine>s[maxn];
     41 
     42 void fun()
     43 {
     44     int k,ans=0,l,r,yl,yr,i;
     45     scanf("%d",&k);k--;
     46     if(vis[k])
     47     {
     48         printf("0
    ");
     49         return ;
     50     }
     51     queue<int> Q;
     52     Q.push(k);vis[k]=true;
     53     while(!Q.empty())
     54     {
     55         ans++;
     56         k=Q.front();Q.pop();
     57         l=lower_bound(f,f+X,p[k].x-p[k].d)-f;//二分查找大于等于val的下标
     58         r=upper_bound(f,f+X,p[k].x+p[k].d)-f;//二分查找“元素值>查找值”的第一个元素的位置
     59         for(i=l;i<r;i++)
     60         {
     61             int dy=p[k].d-abs(p[k].x-f[i]);
     62             multiset<Mine>::iterator it,yl,yr;
     63             yl=s[i].lower_bound(Mine(p[k].y-dy,0));//返回的是指针
     64             yr=s[i].upper_bound(Mine(p[k].y+dy,0));
     65             for(it=yl;it!=yr;it++)
     66             {
     67                 if(!vis[it->n])
     68                 {
     69                     vis[it->n]=true;
     70                     Q.push(it->n);
     71                 }
     72             }
     73             s[i].erase(yl,yr);
     74         }
     75     }
     76     printf("%d
    ",ans);
     77 }
     78 void solve()
     79 {
     80     int i,j;
     81     for(i=0;i<N;i++)
     82     {
     83         p[i]=read_point();
     84         f[i]=p[i].x;
     85     }
     86     sort(f,f+N);
     87     X=unique(f,f+N)-f;
     88     for(i=0;i<X;i++) s[i].clear();
     89     for(i=0;i<N;i++)
     90     {
     91         j=lower_bound(f,f+X,p[i].x)-f;
     92         s[j].insert(Mine(p[i].y,i));
     93     }
     94     memset(vis,false,sizeof(vis));
     95     scanf("%d",&M);
     96     while(M--) 
     97         fun();
     98 }
     99 int main()
    100 {
    101     int icase=0;
    102     while(scanf("%d",&N),N)
    103     {
    104         printf("Case #%d:
    ",++icase);
    105         solve();
    106     }
    107     return 0;
    108 }
     
     
  • 相关阅读:
    vue父组件促发子组件中的方法
    油猴脚本:油猴脚本自动点击 | 自动检测元素并点击、休眠、顺序执行、单页面也适用
    油猴脚本:使用layer.js mobx lodash jquery
    vue项目统计src目录下代码行数
    常用mobx响应新值变化函数autorun和observe
    uni app使用mobx | uni app状态管理mobx
    File and Code Templates | webstorm代码文件模板 vue typescript
    javascript立即执行函数简单介绍
    VSCode 安装GitLens插件不生效问题
    常用的浅拷贝实现方法
  • 原文地址:https://www.cnblogs.com/xiong-/p/3763008.html
Copyright © 2011-2022 走看看