[CTSC99]拯救大兵瑞恩
来源:互联网 发布:西门子s7 300编程软件 编辑:程序博客网 时间:2024/05/16 00:30
一、问题描述
1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但是幸好麦克得到了迷宫的地形图。
迷宫的外形是一个长方形,其在南北方向被划分为N行,在东西方向被划分为M列,于是整个迷宫被划分为N*M个单元。我们用一个有序数对(单元的行号,单元的列号)来表示单元位置。南北或东西方向相邻的两个单元之间可以互通,或者存在一扇锁着的门,又或者存在一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分为P类,打开同一类的门的钥匙相同,打开不同类的门的钥匙不同。
大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,在西北角,也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间忽略不计。
你的任务是帮助麦克以最快的方式抵达瑞恩所在单元,营救大兵瑞恩。
输入:
第一行是三个整数,依次表示N,M,P的值;
第二行是一个整数K,表示迷宫中门和墙的总个数;
第I+2行(1<=I<=K),有5个整数,依次为Xi1,Yi1,Xi2,Yi2,Gi:
当Gi>=1时,表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一扇第Gi类的门,当Gi=0时,表示(Xi1,Yi1)单元与(Xi2,Yi2)单元之间有一堵不可逾越的墙;
(其中,|Xi1-Xi2|+|Yi1-Yi2|=1,0<=Gi<=P)
第K+3行是一个整数S,表示迷宫中存放的钥匙总数;
第K+3+J行(1<=J<=S),有3个整数,依次为Xi1,Yi1,Qi:表示第J把钥匙存放在(Xi1,Yi1)单元里,并且第J把钥匙是用来开启第Qi类门的。(其中1<=Qi<=P)
注意:输入数据中同一行各相邻整数之间用一个空格分隔。
输出:
输出文件只包含一个整数T,表示麦克营救到大兵瑞恩的最短时间的值,若不存在可行的营救方案则输出-1。
输入输出示例:
输入文件
4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1
输出文件
14
参数设定:
3<=N,M<=15;
1<=P<=10;
-------------------------------------------------------------------------------------------------------------------
第一次看到这题时想复杂了,但后来一看数据规模,就想到了搜索,在元素上记录了附带的钥匙信息,需要用到一点位运算,这样就转化为了常规的迷宫最短路,显然BFS,注意下判重,代码附上:
const dx:array[1..4] of longint=(0,-1,1,0); dy:array[1..4] of longint=(-1,0,0,1);var n,m:longint; g:array[1..15,1..15] of record key:longint; wall:array[1..4] of longint; end; v:array[1..15,1..15,0..1024] of boolean; top,last:longint; q:array[0..1024*225] of record state,x,y,dis:longint; end;procedure swap(a,b:longint);begin a:=a xor b; b:=a xor b; a:=a xor b;end;procedure init;var p,k,xi1,yi1,xi2,yi2,gi,s,qi,i:longint;begin assign(input,'rescue.in'); reset(input); fillchar(g,sizeof(g),0); readln(n,m,p); readln(k); for i:=1 to k do begin readln(xi1,yi1,xi2,yi2,gi); if gi=0 then gi:=-1; if (xi1>xi2)or(yi2>yi1) then begin swap(xi1,xi2); swap(yi1,yi2); end; if xi1=xi2 then begin g[xi1,yi1].wall[4]:=gi; g[xi2,yi2].wall[1]:=gi; end else begin g[xi1,yi1].wall[3]:=gi; g[xi2,yi2].wall[2]:=gi; end; end; readln(s); for i:=1 to s do begin readln(xi1,yi1,qi); g[xi1,yi1].key:=g[xi1,yi1].key or (1 shl(qi-1)); end;end;procedure upload(xi,yi,statei,disi:longint);begin if v[xi,yi,statei] then exit; inc(last); with q[last] do begin x:=xi; y:=yi; state:=statei; dis:=disi; end; v[xi,yi,statei]:=true;end;procedure expand(top:longint);var k:longint;begin with q[top] do for k:=1 to 4 do if (x+dx[k]>=1)and(x+dx[k]<=n)and(y+dy[k]>=1)and(y+dy[k]<=m)and(g[x,y].wall[k]<>-1) then begin if g[x,y].wall[k]=0 then upload(x+dx[k],y+dy[k],state or g[x+dx[k],y+dy[k]].key,dis+1); if (g[x,y].wall[k]<>0)and((state shr(g[x,y].wall[k]-1))and 1=1) then upload(x+dx[k],y+dy[k],state or g[x+dx[k],y+dy[k]].key,dis+1); end;end;procedure solve;begin assign(output,'rescue.out'); rewrite(output); fillchar(v,sizeof(v),false); top:=0; last:=0; upload(1,1,g[1,1].key,0); while top<last do begin inc(top); with q[top] do if (x=n)and(y=m) then begin write(dis); close(output); halt; end; expand(top); end; write(-1); close(output);end;begin init; solve;end.
- [CTSC99]拯救大兵瑞恩
- 拯救大兵瑞恩
- 【CTSC1999】【拯救大兵瑞恩】
- 【搜索+状态压缩】拯救大兵瑞恩
- hdu 4845 拯救大兵瑞恩(bfs)
- 软件项目管理与《拯救大兵瑞恩》
- 【HDU4845】拯救大兵瑞恩(BFS+状态压缩)
- 【CTSC1999】拯救大兵瑞恩(孤岛营救问题)
- codevs 1911孤岛营救问题/2219拯救大兵瑞恩
- HDU 4845 拯救大兵瑞恩 基本状态压缩bfs
- HDU 4845 拯救大兵瑞恩(BFS+状态压缩)
- 算法:拯救大兵瑞恩(BFS+状态压缩)
- HDU 5094 Maze & HDU 4845 拯救大兵瑞恩 (BFS + 状压)
- 拯救大兵Touchpad
- [CTSC1999]营救大兵瑞恩
- 《拯救大兵雷恩》是一种什么电影?
- 拯救“大兵”酒吧--空间加香
- 拯救大兵雷诺(递归+回溯)
- SSH框架单元测试工具类
- 【整理】SIMD、MMX、SSE、AVX、3D Now!、neon
- 实例解说Linux中fdisk分区使用方法
- Android学习15--使用(Drawable)资源
- 项目管理/研发管理过程中的一些感悟
- [CTSC99]拯救大兵瑞恩
- 学习总结之ETH OAM:Y.1731与CFM
- 史上最经典的Linux内核学习方法论
- opencv中关于直方图的相关函数
- Android日记之2012/02/08——浅谈Timer
- 获取本机IP地址代码
- 2012寒假总结
- 这个错误时什么原因
- 获取URL