袋鼠妈妈找孩子
Time limit per test: 1.5 seconds
Time limit all tests: 10.0 seconds
Memory limit: 256 megabytes
袋鼠妈妈找不到她的孩子了。她的孩子被怪兽抓走了。
袋鼠妈妈现在在地图的左上角,她的孩子在地图第 x 行第 y 列的位置。怪兽想和袋鼠妈妈玩一个游戏:他不想让袋鼠妈妈过快地找到她的孩子。袋鼠妈妈每秒钟可以向上下左右四个方向跳一格(如果没有墙阻拦的话),怪兽就要在一些格子中造墙,从而完成一个迷宫,使得袋鼠妈妈能够找到她的孩子,但最快不能小于 k 秒。
请设计这样一个迷宫。
Input
第一行两个整数 n,m (1≤n,m≤8) ,表示地图的总行数和总列数。
第二行三个整数 x,y,k (1≤x≤n,1≤y≤m,x+y>1) 。
Output
输出一个地图,应正好 n 行 m 列。
用 .
表示空地,用 *
表示墙。袋鼠妈妈所在的位置和孩子所在的位置用 .
表示。
数据保证有解。
Examples
2 6 1 3 4
.*.*** ......
官方题解:
C. 袋鼠妈妈找孩子
由于数据范围很小,直接搜索就可以了。考虑 DFS,每一个要走的格子,周围最多只能有一格(其实就是走过来的那一格)是走过的。全部搜一遍就结束了。
出题人:过的人少得不可思议。
比赛的时候没有做出来,然后看了官方给的题解之后,有了思路。
思路详述:
暴力求解,搜索一条路径,其从起点到终点的时间大于等于k。当然这个路不是随便选的,走哪是需要条件判断的。为了让袋鼠妈妈沿着我深搜的符合条件的路径走,
我需要采取一些措施,措施如下,假设当前袋鼠妈妈的位置为(x,y),假设她下一秒往右走,那么我就要把(x,y)位置的上方,下方,左方都设成墙,这样的话,
她别无选择了,只能往右走了,同时保留其他三个方向的原始状态,因为回溯的时候还要恢复那三个点的状态。也就是说,搜索方向有四个,如果朝某个方向走,
则除该方向外的其他方向直接封锁,一直这样进行下去,直到找到一条符合条件的路径。在深搜中定义flag变量,标记是否已经找到一组解,当找到第一个符合
条件的解的时候,就把flag变成true.在深搜开始的时候,就先判断flag的值,如果,flag已经是true了,直接返回即可,题目只要一组解,找到解后继续搜索并没有什么
意义而且也浪费时间。
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn = 10;
int Map[maxn][maxn];
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
///搜索方向上、右、下、左。
int n,m;
int x,y,k;
bool flag;
///用于标记是否已经找到可行解。
/**以sx,sy为新起点进行搜索,并且从起点到(sx,sy)
已经走了step步**/
void dfs(int sx,int sy,int step)
{
int a[5];
if(flag) ///有一组可行解
return;
Map[sx][sy] = 1; ///标记为1,代表这个位置走过了。
if(sx == x && sy == y) ///到达目标
{
if(step >= k) ///如果步数大于等于k,是解。
{
///直接输出地图,flag变为true
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(Map[i][j]==1 || Map[i][j]==0)
printf(".");
else
printf("*");
}
printf("\n");
}
flag = true;
}
return; ///找没找到解都要返回
}
for(int i = 0; i < 4; i++) ///进行四个方向的搜索
{
int tx = sx + dir[i][0];
int ty = sy + dir[i][1];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&Map[tx][ty]==0)
{
/**为了让袋鼠妈妈走tx,ty这一点,我要逼她无路可走,
让她只能从(sx,sy)走到(tx,ty),因此封锁(sx,sy)周围除
(tx,ty)以外的其他点**/
for(int j = 0; j < 4; j++)
{
if(i == j) continue;
int tempx = sx + dir[j][0];
int tempy = sy + dir[j][1];
a[j] = Map[tempx][tempy];
///数组a用来保留,(sx,sy)周围点的原始状态,回溯要用到
if(tempx<1||tempx>n||tempy<1||tempy>m) continue;
if(Map[tempx][tempy]==0) ///只有是空地才可以封锁
Map[tempx][tempy] = 2;
}
dfs(tx,ty,step+1); ///以(tx,ty)为起点,进行深搜
Map[tx][ty] = 0; ///回溯,变为0,代表该点没有走过
for(int j = 0; j < 4; j++)
{
if(i == j) continue;
int tempx = sx + dir[j][0];
int tempy = sy + dir[j][1];
if(tempx<1||tempx>n||tempy<1||tempy>m) continue;
Map[tempx][tempy] = a[j];
///恢复(sx,sy)周围点的原始状态。
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
scanf("%d%d%d",&x,&y,&k);
memset(Map,0,sizeof(Map)); ///代表这个位置是'.'
flag = false;
dfs(1,1,0);
}
}