进攻幽暗城

进攻幽暗城
(attack.pas/c/cpp)
【问题描述】
由于震惊海内外的“愤怒门投毒事件”的发生,部落为了对抗皇家药剂师协会的叛乱,所有的外交
工作完成后,部落大酋长萨尔带领着小A 穿过传送门到达幽暗城平叛。
幽暗城的地图是一个N*M 的 01 串。a[i,j]=1 时表示(i,j)的位置是障碍,无法通过;a[i,j]=0 时
表示(i,j)的位置可以进入。
小 A 与萨尔的初始位置是(x1,y1),而恐惧魔王的初始位置是(x2,y2)。小 A 的目标就是到达恐惧魔
王的位置。
萨尔会按照一个特定的路线行走,该路线是一个数字串,由 0-4组成。第i 秒,若数字串第(i mod
数字串的长度)位=0,则表示这一秒萨尔将会原地不动;=1,则表示这一秒萨尔会向上走一格;=2,则
表示这一秒萨尔会向下走一格;=3,则表示这一秒萨尔会向左走一格;=4,则表示这一秒萨尔会向右走
一格。若萨尔将要移动的位置是墙或者超出迷宫的范围,则萨尔会原地不动。恐惧魔王也是这样。(换
句话说,你可以认为如果将数字串是重复无限次,第 i 秒就是字符串第i 位)
小A 每秒可以选择从上下左右四个方向中选择一个方向,朝那个方向走一格,前提是那个位置不是
墙并且没有超出迷宫的范围;或者原地不动。不过,由于幽暗城的诡异环境,小 A 只能持续脱离萨尔的
光环 s 秒,若超过 s 秒小 A 则会死亡。光环的有效半径为 d,表示当小 A 与萨尔之间的距离
√(x ? xx)2 + (y ? yy)2,小于等于 d 时小 A 才能受到萨尔光环的效果。若小 A 脱离萨尔的光环又重新
进入光环有效区域,则再次离开光环时持续时间归零重记。
小A 想知道最少需要几秒他才能到达恐惧魔王所在的位置。
【输入格式】
第一行四个数N,M,s,d。
接下来的N 行,每行M 个数(0或1),之间没有空格,表示幽暗城的地图。
接下来的一行四个整数,x1,y1,x2,y2(1≤x1,x2≤N,1≤y1,y2≤M)。
接下来的一行是一个数字串,表示萨尔的移动方式。
接下来的一行是一个数字串,表示恐惧魔王的移动方式。
【输出格式】
输出共一行一个整数,表示需要最少的时间。
【输入样例】
3 4 7 3
1010
0000
0101
1 2 3 3
0132401
12131

【输出样例】
3

【数据规模】
对于100%的数据:1≤N,M≤50;0≤s≤1000;0≤d≤100;1≤数字串长度≤1,000;0≤答案≤100。

这个图论很诡异喂,终点居然可以动,更可恶的是还有那什么什么破光环,还有限制,真 是气史宝宝了。其实,这题由于数据较小,还是能杀下来 滴。。首先,我们要把魔王和萨尔的行踪记录下来。难点 主要在于光环处。当然,如果没有光环限制,无论刷bfs还 是spfa都能搞定。那么有光环也差不多。那么,我们用dst [x][y][t]表示当前处于x,y,并且已经走了t秒,此时脱离光环 的时间。那么,我们要判断的是什么呢?我们无非不能小A脱离光环超过s秒。那么,只要满足了 dst[tx][ty][t+1]<=s就行了。tx,ty是当前将要走到的位置 当然,判断前还要更新 dst[tx][ty][t+1]:=check(dst[x][y][t],tx,ty,t+1);当然,这 是在dst[tx][ty][t+1]>check(dst[x][y][t],tx,ty,t+1)的情况 下更新的。check(num,x,y,t)怎么写?只要在光环里就行了。 if sqr(x-pos_sa[t].x)+sqr(y-pos_sa[t].y)<=sqr(d) then exit(0) else exit(num+1);如果回到光环内,那么时 间清0,否则继续。更新好后是否入队呢?不一定,仅当 (vis[tx][ty][t+1]) or (dst[tx][ty][t+1]>s)这个状态没走过 时或者小A在这种情况下没死时,入队。那么,可以刷bfs 也可以刷spfa。那么,当某次小A的坐标等于魔王的坐标时 把时间输出就好了啊。o_O

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #define sqr(x) ((x)*(x))
 6 using namespace std;
 7 const int maxn=55,maxt=105,maxv=55*55*105,fl[5][2]={{0,0},{-1,0},{1,0},{0,-1},{0,1}};
 8 char sa[maxt],mo[maxt];
 9 bool vis[maxn][maxn][maxt];
10 int n,m,s,d;
11 int grp[maxn][maxn],dst[maxn][maxn][maxt];
12 int x_sa,y_sa,l_sa,x_mo,y_mo,l_mo,x_a,y_a;
13 int x1,y1,x2,y2,tx,ty;
14 int hd,tl;
15 struct data{
16     int x,y,t;
17 }p_sa[maxt],p_mo[maxt],qu[maxv];
18 
19 void _init(){
20     scanf("%d%d%d%d",&n,&m,&s,&d);
21     char ch;
22     for (int i=1; i<=n; i++){
23         int x=0;
24         while (x<m){
25             x++; ch=getchar();
26             while (ch<'0'||ch>'1') ch=getchar();
27             grp[i][x]=(ch=='1');
28         }
29     }
30     memset(sa,0,sizeof(sa));
31     memset(mo,0,sizeof(mo));
32     scanf("%d%d%d%d",&x_sa,&y_sa,&x_mo,&y_mo); x_a=x_sa,y_a=y_sa;
33     ch=getchar();
34     while (ch<'0'||ch>'4') ch=getchar();
35     while (ch>='0'&&ch<='4') sa[++l_sa]=ch,ch=getchar();
36     ch=getchar();
37     while (ch<'0'||ch>'4') ch=getchar();
38     while (ch>='0'&&ch<='4') mo[++l_mo]=ch,ch=getchar();
39 }
40 void write(int ans){
41     printf("%d",ans); exit(0);
42 }
43 bool chk_rg(int x,int y){
44     if (x<1||x>n||y<1||y>m) return false;
45     return grp[x][y]==0;
46 }
47 int chk_tm(int now,int x,int y,int t){
48     if (sqr(x-p_sa[t].x)+sqr(y-p_sa[t].y)<=sqr(d)) return 0; else return now+1;
49 }
50 void _move(int nowt){
51     tx=x1+fl[sa[((nowt-1)%l_sa)+1]-'0'][0],ty=y1+fl[sa[((nowt-1)%l_sa)+1]-'0'][1];
52     if (chk_rg(tx,ty)) { x1=tx,y1=ty; }
53     tx=x2+fl[mo[((nowt-1)%l_mo)+1]-'0'][0],ty=y2+fl[mo[((nowt-1)%l_mo)+1]-'0'][1];
54     if (chk_rg(tx,ty)) { x2=tx,y2=ty; }
55     p_sa[nowt]={x1,y1,0},p_mo[nowt]={x2,y2,0};
56 }
57 void _spfa(){
58     memset(vis,0,sizeof(vis));
59     memset(dst,63,sizeof(dst));
60     dst[x_a][y_a][0]=0; vis[x_a][y_a][0]=1;
61     hd=0; tl=1; qu[1]={x_a,y_a,0};
62     while (hd!=tl){
63         hd=(hd+1)%maxv; int x=qu[hd].x,y=qu[hd].y,t=qu[hd].t; vis[x][y][t]=0;
64         if (x==p_mo[t].x&&y==p_mo[t].y) write(t);
65         for (int i=0; i<=4; i++){
66             tx=x+fl[i][0],ty=y+fl[i][1];
67             if (!chk_rg(tx,ty)) continue;
68             int t_need=chk_tm(dst[x][y][t],tx,ty,t+1);
69             if (dst[tx][ty][t+1]<=t_need) continue;
70             dst[tx][ty][t+1]=t_need;
71             if (vis[tx][ty][t+1]||dst[tx][ty][t+1]>s) continue;
72             tl=(tl+1)%maxv; qu[tl]={tx,ty,t+1}; vis[tx][ty][t+1]=1;
73         }
74     }
75 }
76 void _work(){
77     x1=x_sa,y1=y_sa,x2=x_mo,y2=y_mo;
78     p_sa[0]={x1,y1,0}; p_mo[0]={x2,y2,0};
79     for (int i=1; i<=100; i++) _move(i);
80     _spfa();
81 }
82 int main(){
83     _init();
84     _work();
85     return 0;
86 }
View Code

 

转载于:https://www.cnblogs.com/whc200305/p/7112717.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值