博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jzoj100048. 紧急撤离
阅读量:4587 次
发布时间:2019-06-09

本文共 9821 字,大约阅读时间需要 32 分钟。

Description

某日, 敌军对某村落展开攻击,所幸我情报部门提前预知了消息,村民兵武装连夜组织村民快速转移,为此他们需要赶往地道入口。已知村庄形成了 N * M 的方格网络,周围被封锁,无法穿行。其中有些方格没有敌军占领,可以进入,有些方格已经被敌军渗透,不能进入。由于敌军的步步紧逼,民众只能向行或列增大的地方移动:即(x, y) → (x + 1, y)或(x, y) → (x, y + 1)。 机智的 Star 手提笔记本,正和民兵队长商议对策。民兵队长会问你 Q 个问 题,每个问题均类似于坐标(a, b)的村民能否安全到达位于坐标(c, d)的地道(队长是机智的,他的问题总保证起点和终点均安全),你需要赶快写出程序来帮助他。

Input

第 1 行两个整数 N, M;

第 2 ~ n + 1 行给出一个 N * M 的 0/1 矩形(每行可看作一字符串),其中 0 表示安全,1 表示不安全,设第 i + 1 行第 j 列的位置坐标为(i, j)。
第 n + 2 行一个整数 Q;
接下来 Q 行每行四个整数 a、b、c、d,保证坐标合法。

Output

对于每组询问,输出一行“Safe”或“Dangerous”。

Sample Input

7 7

0100000
0000010
0001010
0011000
1000010
0000000
0111001
5
3 3 4 6
6 1 6 7
4 5 6 5
3 3 4 5
4 6 7 6

Sample Output

Dangerous

Safe
Safe
Dangerous
Dangerous

Data Constraint

对于 30%的数据,n, m ≤ 50;

对于另外 20%的数据,n, m ≤ 200、q ≤ 1000;
对于 100%的数据,n, m ≤ 500、q ≤ 600000。

题解

此题为坑题。

坑在何处?卡你常数。
首先,这题我们发现,一个点每次只能从某个点依次往下或往右走,走到结束点。
那么直观的想法——求出两两点之间最短路径,然后O(1)判断即可。
然而这种方法只可以过30分。
那么再想想,发现另外20分很好弄,于是可以暴力得到50分的好成绩。
可是100分呢?
由于求两两点之间的最短路,那么就用到的是弗洛伊德。
弗洛伊德有一个中转点,那么我们就可以考虑从起点到中转点再到终点看看可否行得通。
那么就有一个直观的想法——分治。
我们考虑500*500中,从列里面分治,枚举中间列,然后找出从中间穿过的询问,DP求出状态即可。
一步一步来看——
首先枚举中间列,就是每次分治下去,不用讲了吧。
其次是找出从中间穿过的询问。
我们考虑先把询问都按照起点的y坐标从小到大排序,然后,建一个双向链表,做过的询问就从链表中删掉。
可以优化时间——O(qlog⁡n)O(q \log n)O(qlogn)
当然,如果快排太慢,可以考虑桶排。
最后是DP。
我们设一个f[i,j]表示从中间的列右边的某个点反向走能够走到中间列状态,一个g示从中间的列左边的某个点正向走能够走到中间列状态
这个状态是二进制的,虽说有25002^{500}2500但是我们可以考虑压位,当然,C++可以用bitset。
O(n3∗log⁡n/ω)O(n^3*\log n/ \omega)O(n3logn/ω)
具体时间很简单,只是时间可能卡的紧些。

代码

{
$inline on}uses math;type new=record x,y:longint; end; new1=array of longint;var i,j,k,l,n,m,q,answer,up:longint; map:array[1..500,1..500] of boolean; wz:array[1..500,1..500] of new; x1,y1,x2,y2,id,da:array[1..600000] of longint; xx1,yy1,xx2,yy2,idd:array[1..600000] of longint; ans:array[1..600000] of longint; s:ansistring; f,g:array[1..500,1..500,0..9] of int64; mi:array[0..60] of int64; wz1,wz2:array[1..500] of longint; t:array[1..500] of new1; next,last:array[0..600000] of longint; z:array[0..600000] of longint;{
procedure bfs(i,j,mbx,mby:longint);var k,l,x,y,nx,ny,head,tail,took:longint;begin head:=1; tail:=1; took:=1; ans[1]:=0; repeat for k:=head to tail do begin for l:=1 to 2 do begin begin if map[nx,ny] then begin end; end; end; end; head:=tail+1; tail:=took; until head>tail;end;procedure gc;inline;var i,j:longint;begin for i:=1 to n do begin for j:=1 to m do begin bfs(i,j,0,0); end; end;end;}procedure tsort;inline;var i,j,k:longint;begin for i:=1 to 500 do begin setlength(t[i],1); t[i,0]:=0; end; for i:=1 to q do begin setlength(t[y1[i]],t[y1[i],0]+2); inc(t[y1[i],0]); t[y1[i],t[y1[i],0]]:=i; end; k:=0; for i:=1 to 500 do begin for j:=1 to t[i,0] do begin inc(k); xx1[k]:=x1[t[i,j]]; yy1[k]:=y1[t[i,j]]; xx2[k]:=x2[t[i,j]]; yy2[k]:=y2[t[i,j]]; idd[k]:=id[t[i,j]]; end; end; for i:=1 to k do begin x1[i]:=xx1[i];y1[i]:=yy1[i];x2[i]:=xx2[i];y2[i]:=yy2[i];id[i]:=idd[i]; end;end;procedure daan(l,r:longint);inline;var i,j,k,min1,max1,min2,max2,mid:longint;begin if l>r then exit; mid:=(l+r) div 2; z[0]:=0; min1:=maxlongint; max1:=0; min2:=maxlongint; max2:=0; i:=next[0]; while i<=q do begin if (y1[i]>=l)and(y1[i]<=mid)and(y2[i]>=mid)and(y2[i]<=r) then begin min1:=min(min1,y1[i]); max1:=max(max1,y2[i]); min2:=min(min2,x1[i]); max2:=max(max2,x2[i]); inc(z[0]); z[z[0]]:=i; last[next[i]]:=last[i]; next[last[i]]:=next[i]; end; i:=next[i]; if (i=0) or (y1[i]>mid) then break; end; if z[0]=0 then begin daan(l,mid-1); daan(mid+1,r); end else begin for i:=1 to 500 do begin for j:=min1 to max1 do begin fillchar(f[i,j],sizeof(f[i,j]),0); fillchar(g[i,j],sizeof(g[i,j]),0); end; end; if (map[1,mid]) then f[1,mid,wz2[1]]:=f[1,mid,wz2[1]] or mi[wz1[1]]; if (map[n,mid]) then g[n,mid,wz2[n]]:=g[n,mid,wz2[n]] or mi[wz1[n]]; for i:=2 to max2 do begin if map[i,mid] then begin if map[i-1,mid] then f[i,mid]:=f[i-1,mid]; f[i,mid,wz2[i]]:=f[i,mid,wz2[i]] or mi[wz1[i]]; end; end; for i:=n-1 downto min2 do begin if map[i,mid] then begin if map[i+1,mid] then g[i,mid]:=g[i+1,mid]; g[i,mid,wz2[i]]:=g[i,mid,wz2[i]] or mi[wz1[i]]; end; end; for i:=mid+1 to max1 do begin if map[1,i-1] then begin for k:=1 to up do begin f[1,i,k]:=f[1,i,k] or f[1,i-1,k]; end; end; for j:=2 to max2 do begin if map[j,i] then begin if map[j-1,i] then f[j,i]:=f[j-1,i]; if map[j,i-1] then begin for k:=1 to up do begin f[j,i,k]:=f[j,i,k] or f[j,i-1,k]; end; end; end; end; end; for i:=mid-1 downto min1 do begin if map[n,i+1] then begin for k:=1 to up do begin g[n,i,k]:=g[n,i,k] or g[n,i+1,k]; end; end; for j:=n-1 downto min2 do begin if map[j,i] then begin if map[j+1,i] then g[j,i]:=g[j+1,i]; if map[j,i+1] then begin for k:=1 to up do begin g[j,i,k]:=g[j,i,k] or g[j,i+1,k]; end; end; end; end; end; for i:=1 to z[0] do begin j:=z[i]; for k:=1 to up do begin if g[x1[j],y1[j],k] and f[x2[j],y2[j],k]>0 then begin ans[id[j]]:=1; break; end; end; if ans[id[j]]=0 then ans[id[j]]:=-1; end; daan(l,mid-1); daan(mid+1,r); end;end;begin //assign(input,'0data.in');reset(input); //assign(output,'0data.out');rewrite(output); readln(n,m); up:=n div 60; if n mod 60>0 then inc(up); mi[0]:=1; for i:=1 to 60 do mi[i]:=mi[i-1]*2; for i:=1 to n do begin wz1[i]:=(i-1) mod 60; wz2[i]:=i div 60+1; end; for i:=1 to n do begin readln(s); for j:=1 to m do begin if s[j]='0' then map[i,j]:=true else map[i,j]:=false; end; end; readln(q); for i:=1 to q do begin read(x1[i],y1[i],x2[i],y2[i]); id[i]:=i; end; tsort; next[0]:=1; next[q]:=q+1; for i:=2 to q do begin next[i-1]:=i; last[i]:=i-1; end; daan(1,m); for i:=1 to q do begin if ans[i]=1 then writeln('Safe'); if ans[i]=-1 then writeln('Dangerous'); end;end.

转载于:https://www.cnblogs.com/RainbowCrown/p/11148378.html

你可能感兴趣的文章
BLE广播数据的抓包解析
查看>>
基于 Android NDK 的学习之旅-----HelloWorld
查看>>
JAVA CAS原理深度分析
查看>>
initWithFrame方法的理解
查看>>
cocos2d-x的lua脚本加载CocostudioUI两种方式
查看>>
目标文件符号《深入理解计算机系统》笔记(三)链接知识【附图】
查看>>
The import org.cocos2dx.lib cannot be resolved
查看>>
黑马程序员-java基础学习IO流4
查看>>
SolrCloud使用问题记录
查看>>
提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)
查看>>
mybatis入门基础(二)----原始dao的开发和mapper代理开发
查看>>
linux网络流程分析(一)---网卡驱动
查看>>
2016年毕业设计指导与总结
查看>>
TypeError: Cannot read property 'tap' of undefined
查看>>
scikit-learn文本特征提取之TF-IDF
查看>>
WebApiTestClient自定义返回值说明
查看>>
Swift中文教程(二)--简单值
查看>>
H3C 维护命令
查看>>
根据状态变化情况,求最大值和最小值
查看>>
解决Windows10下小娜无法搜索本地应用的问题
查看>>