测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A39864. 打怪救公主公主被魔王抓起来关在了迷宫的某处,骑士想要拯救公主,也进入了迷宫。但是魔王不会轻易让骑士拯救公主,魔王在迷宫中安排了许多怪兽。每个怪兽都有血量,骑士也有初始血量,骑士打败怪兽后血量的减少量为怪物的血量值,血量减到0,骑士会死去。迷宫由m*n个方块组成,每个方块有墙或者路或者怪物,骑士在其中一个方块上,他每个时间单位可以四个方向(上、下、左、右)走到相邻方格,若遇到怪物,必须打败怪物才能…

填空题 困难

题目描述

打怪救公主

公主被魔王抓起来关在了迷宫的某处,骑士想要拯救公主,也进入了迷宫。

但是魔王不会轻易让骑士拯救公主,魔王在迷宫中安排了许多怪兽。

每个怪兽都有血量,骑士也有初始血量,骑士打败怪兽后血量的减少量为怪物的血量值,血量减到0,骑士会死去。

迷宫由m*n个方块组成,每个方块有墙或者路或者怪物,骑士在其中一个方块上,他每个时间单位可以四个方向(上、下、左、右)走到相邻方格,若遇到怪物,必须打败怪物才能继续前进。

请帮忙判断骑士能否成功拯救公主,如果能,给出骑士还剩的最大血量。

输入

第一行为三个整数m、n和t,t表示骑士的初始血量。(m,n <= 20, t <= 30) 第2至m+1行描述了迷宫,迷宫以m行n列的方格组成,若方格为"."则表示骑士可以通过,若方格为"#"则表示墙,骑士不能通过,若方格为数字则表示怪物,数字为怪物的血量,保证怪物的血量小于10(一位数)。"*"表示了骑士当前所在的位置,"+"表示公主被囚禁的位置。

输出

若骑士能成功拯救公主,则输出骑士走到公主所囚禁方格所剩最大血量,否则输出0。

样例输入

5 6 10

..*...

.#2###

5#..4#

.##9.#

.#+..#

样例输出

4

参考答案

#include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; struct POINT { int x,y,tot; //坐标,步数 bool get_jewel[7],enchantment; //找到的宝石,结界 } point,door; int main() { int k,F[4][2]={-1,0,1,0,0,-1,0,1}; scanf("%d",&k); for(int kk=1;kk<=k;kk++) { /*定义*/ queue<POINT> que; //队列 int r,c,needkind,door_coord[15][2]={},sdoor_coord=0; //边界,需要的宝石种类,传送门坐标,传送门个数 char maze[205][205]={};//迷宫 bool walked[205][205][35]={},finish=false; //已经走过的路,第三维是宝石数(2进制);是否完成 /*输入*/ scanf("%d%d%d",&r,&c,&needkind); for(int i=0;i<r;i++) { scanf("%s",maze[i]); for(int j=0;j<c;j++) { if(maze[i][j]=='S') //起点 { memset(point.get_jewel,false,sizeof(point.get_jewel)); point.x=i;point.y=j;point.tot=0;point.enchantment=true; } if(maze[i][j]=='$') //传送门 { door_coord[sdoor_coord][0]=i; //存入位置 door_coord[sdoor_coord++][1]=j; } } } /*广度优先搜索*/ que.push(point); //存入起点 while(!que.empty()) //队列不为空 { for(int i=0;i<4;i++) //4个方向 { point=que.front(); //直接等 point.tot++;point.x+=F[i][0];point.y+=F[i][1]; //改坐标,改步数 if(point.x<0 || point.x>=r || point.y<0 || point.y>=c || maze[point.x][point.y]=='#') continue; //超界或为墙 if('0'<=maze[point.x][point.y] && maze[point.x][point.y]<='4') //如果为宝石 point.get_jewel[maze[point.x][point.y]-'0']=true; //改变point中该宝石的值为 “找到 ” int sget_jewel=0,ss=0; //找到的宝石个数 for(int i=0;i<5;i++) if(point.get_jewel[i]) //遍历宝石获得数 sget_jewel+=pow(2,i),ss++; //eg:获得0,3 --> 2进制:01001=9 if(walked[point.x][point.y][sget_jewel]) continue; //如果之前到达过该位置且未找到更多的宝石 walked[point.x][point.y][sget_jewel]=true; //改变该位置的到达记录 if(ss>=needkind) point.enchantment=false; //如果找到了足够的宝石,结界消失 if(maze[point.x][point.y]=='$') //如果是传送门 { door=point; //保存位置 for(int i=0;i<sdoor_coord;i++) //遍历所有传送门 if(door_coord[i][0]!=point.x || door_coord[i][1]!=point.y) //不是当前的位置 { door.x=door_coord[i][0];door.y=door_coord[i][1]; //存入传送门 que.push(door); } } if(maze[point.x][point.y]=='E' && !point.enchantment) //如果是找到终点并且没有结界 { printf("%d\n",point.tot); finish=true; //找到 } if(finish) break; //找到退出 que.push(point); //存入当前位置 } if(finish) break; //找到退出 que.pop(); //出队 } if(!finish) printf("oop!\n"); //没有找到 } return 0; }
上一题 下一题