胜利大逃亡(续) |
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) |
Total Submission(s): 60 Accepted Submission(s): 40 |
|
Problem Description
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……
这次魔王汲取了上次的教训,把Ignatius关在一 个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在 (ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原 位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离 开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。 |
Input
每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:
. 代表路 * 代表墙 @ 代表Ignatius的起始位置 ^ 代表地牢的出口 A-J 代表带锁的门,对应的钥匙分别为a-j a-j 代表钥匙,对应的门分别为A-J 每组测试数据之间有一个空行。 |
Output
针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。
|
Sample Input
4 5 17 @A.B. a*.*. *..*^ c..b* 4 5 16 @A.B. a*.*. *..*^ c..b* |
Sample Output
16 -1 |
思路:BFS,用二进制表示钥匙,那么每一个点用f[i][j][k] 表示是i.j这个点,k的二进制上的1表示拥有哪一把钥匙
总复杂度2^10*20*20
1 /* 2 Author:wuhuajun 3 */ 4 #include <cmath> 5 #include <cstdio> 6 #include <algorithm> 7 #include <cstring> 8 #include <string> 9 #include <cstdlib> 10 #include <queue> 11 using namespace std; 12 13 typedef long long ll; 14 typedef double dd; 15 const int maxn=22; 16 const int dx[]={1,-1,0,0}; 17 const int dy[]={0,0,1,-1}; 18 char s[maxn][maxn],ch; 19 bool f[maxn][maxn][(1<<10)+10]; 20 struct qq 21 { 22 int x,y,v; 23 } ya,pu; 24 queue<qq> q; 25 int step,l,n,m,t,xx,yy,sx,sy,ex,ey,deadline,pos; 26 bool flag; 27 28 29 void close() 30 { 31 exit(0); 32 } 33 bool reach() 34 { 35 if (xx==ex && yy==ey) 36 { 37 if (step<deadline) 38 printf("%d\n",step); 39 else 40 printf("-1\n"); 41 flag=true; 42 return true; 43 } 44 return false; 45 } 46 47 void print() 48 { 49 for (int i=8;i>=1;i--) 50 printf("%d",pos & (i<<1)); 51 puts(""); 52 } 53 54 void pushin() 55 { 56 pu=ya; 57 pu.x=xx; pu.y=yy; 58 if (t!=0) 59 pu.v=ya.v | (1<<(t-1)); 60 q.push(pu); 61 } 62 63 void judge() 64 { 65 if (!(1<=xx && xx<=n && 1<=yy && yy<=m)) return; 66 ch=s[xx][yy]; 67 if (ch=='*') return;//wall 68 if (ch=='.' || ch=='@') 69 { 70 t=0; 71 if (f[xx][yy][ya.v]) return; 72 f[xx][yy][ya.v]=true; 73 pushin(); 74 return; 75 } 76 if ('a'<=ch && ch<='j') //key 77 { 78 t=ch-'a'+1; 79 pos=ya.v | (1<<(t-1)); 80 if (f[xx][yy][pos]) return;//是否到过(xx,yy)这个点 81 f[xx][yy][pos]=true; 82 pushin(); 83 } 84 else 85 { //door 86 t=ch-'A'+1; 87 if ((ya.v & (1<<(t-1)))==0) return;//在(ya.x,ya.y)点上钥匙不能开门 88 if (f[xx][yy][ya.v]) return; 89 f[xx][yy][ya.v]=true; 90 t=0; 91 pushin(); 92 } 93 } 94 95 void work() 96 { 97 memset(f,false,sizeof(f)); 98 while (!q.empty()) q.pop(); 99 step=0; flag=true; 100 ////////////////// 101 f[sx][sy][0]=true; 102 ya.x=sx; 103 ya.y=sy; 104 ya.v=0; 105 q.push(ya); 106 while (!q.empty()) 107 { 108 step++; 109 //printf("Step:%d\n-----------------------\n",step-1); 110 l=q.size(); 111 while (l--) 112 { 113 ya=q.front(); 114 q.pop(); 115 // printf("x:%d y:%d v:%d\n",ya.x,ya.y,ya.v); 116 for (int i=0;i<4;i++) 117 { 118 xx=dx[i]+ya.x; 119 yy=dy[i]+ya.y; 120 if (reach()) return; 121 judge(); 122 } 123 } 124 } 125 printf("-1\n"); 126 } 127 128 129 void init() 130 { 131 while (scanf("%d %d %d",&n,&m,&deadline)!=EOF) 132 { 133 for (int i=1;i<=n;i++) 134 { 135 scanf("%s",s[i]); 136 for (int j=m-1;j>=0;j--) 137 s[i][j+1]=s[i][j]; 138 s[i][0]='\0'; 139 } 140 for (int i=1;i<=n;i++) 141 for (int j=1;j<=m;j++) 142 { 143 if (s[i][j]=='@') 144 { 145 sx=i;sy=j; 146 } 147 if (s[i][j]=='^') 148 { 149 ex=i; ey=j; 150 } 151 } 152 work(); 153 } 154 } 155 156 int main () 157 { 158 init(); 159 close(); 160 return 0; 161 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】博客园2025新款「AI繁忙」系列T恤上架,前往周边小店选购
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Hangfire Redis 实现秒级定时任务,使用 CQRS 实现动态执行代码
· Android编译时动态插入代码原理与实践
· 解锁.NET 9性能优化黑科技:从内存管理到Web性能的最全指南
· 通过一个DEMO理解MCP(模型上下文协议)的生命周期
· MySQL下200GB大表备份,利用传输表空间解决停服发版表备份问题
· 工良出品 | 长文讲解 MCP 和案例实战
· 多年后再做Web开发,AI帮大忙
· 国产的 Java Solon v3.2.0 发布(央企信创的优选)
· centos停服,迁移centos7.3系统到新搭建的openEuler
· (原创)[开源][.Net Framework 4.0] SimpleLiveDataFeed(极易