Problem C: C
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 36 Solved: 5
[ Submit][ Status][ Web Board]
Description
X opened his eyes slowly and found himself in a strange place. He remembered that he was kidnaped by alien last night. He looked around, relized that he was at a rectangular mountaintop which is a matrix of N * M, and surround by cliffs.
X must be very careful otherwise he might fell off the cliffs. There are many stone walls on the mountaintop. X also found a note in his pocket, says "Your cellphone is at somewhere on the mountop, find it and call your friend Mario for help!". X was able to move one space at four directions (up, down, left, right) every second, of course he can't move on a stone wall. X had 3 bananas in his bag, and he could stand on an banana-peel to slide towards a direction until he hit the wall or fall off the cliffs in one second. Every banana-peel can only be used only one time.
Suddenly, X remembered he had learnt the skill of jumping-over-wall from Y. He could jump over one or some consecutive stone walls in one of the four directions(Of course he can't stand on a stone wall).
It takes 1 second for one jump, he can jump only when he beside the wall and he can't jump over a grid which there isn't a wall. Every one unit of wall costs him 1 energy to jump. He eat 3 bananas, so he have 3 energy initially.
X want to return to his dormitory to play LOL as soon as possible, can you help him find the cellphone?
Input
There are many test cases (the number of test cases <= 100).
Each case starts with two number N and M, indicate the size of the mountaintop. Then, there is a map of N * M (see the format in Sample Input), "0" represent the empty space and "1" is the stone walls, "c" is X's location, "p" is the cellphone's location, and there are not stone walls in the grids of the X's location and the cellphone's location. (0 < n, m <= 1000)
Output
For each test case, output a integer in a line, indicating the minimum time that X spends to find his phone. the alien guarantees that X is able to find his phone.
Sample Input
7 10c01111p1100000011000000101000000100111001111000101000110000100000010012 2c00p
Sample Output
52
HINT
四维状态的宽搜。
启示:尽可能将一些琐碎的模块独立出来,比如找到四个方向上最近的石头(独立出来之后,可以更自由地控制对于特殊情况(如没有石头和紧临石头)的处理。
#include <cstdio>
#include <cstring>
const int mod = 4000010;
struct node
{
int x;
int y;
int en;
int ba;
int t;
//int f;///
};
node que[mod];
node u,v;
int n,m;
const int maxn = 1010;
char map[maxn][maxn];
int rightnear[maxn][maxn];
int leftnear[maxn][maxn];
int upnear[maxn][maxn];
int downnear[maxn][maxn];
bool vis[1010][1010][4][4];
void inc(int& l)
{
l ++;
if (l == mod)
l = 0;
}
inline bool wall(int x,int y)
{
return map[x][y] == '1';
}
inline bool inrange(int x,int y)
{
return x>=1 && x<=n && y>=1 && y<=m;
}
const int dx[4] = {0,-1,0,1};
const int dy[4] = {-1,0,1,0};
int nearest(int x,int y,int d)
{
switch (d)
{
case 0:
if (leftnear[x][y] > -1)
return y-leftnear[x][y]-1;
break;
case 2:
if (rightnear[x][y] < m+1)
return rightnear[x][y]-y-1;
break;
case 1:
if (upnear[x][y] > -1)
return x-upnear[x][y]-1;
break;
case 3:
if (downnear[x][y] < n+1)
return downnear[x][y]-x-1;
break;
}
return -1;
}
int bfs(int sx,int sy,int tx,int ty)
{
int l = 0;
int r = 0;
inc(r);
que[r].t = 0;
que[r].x = sx;
que[r].y = sy;
que[r].en = 3;
que[r].ba = 3;
memset(vis,0,sizeof vis);
//que[r].f = 0;///
vis[sx][sy][3][3] = true;
while (l != r)
{
inc(l);
u = que[l];
//printf("Debug (%d,%d) t:%d en:%d ba:%d\n",u.x,u.y,u.t,u.en,u.ba);
if (u.x == tx && u.y == ty)
{
//Debug
/*
int now = l;
while (now != 0)
{
v = que[now];
printf("Debug (%d,%d) t:%d en:%d ba:%d\n",v.x,v.y,v.t,v.en,v.ba);
now = que[now].f;
}
*/
return u.t;
}
for (int d=0;d<4;d++)
{
v=u;
v.x += dx[d];
v.y += dy[d];
v.t ++;
if (inrange(v.x,v.y) && !wall(v.x,v.y) && !vis[v.x][v.y][v.ba][v.en])
{
vis[v.x][v.y][v.ba][v.en] = true;
inc(r);
que[r] = v;
//que[r].f = l;//
}
}
if (u.ba > 0)
{
for (int d=0;d<4;d++)
{
int _m = nearest(u.x,u.y,d);
if (_m!=-1)
{
v = u;
v.x += dx[d]*_m;
v.y += dy[d]*_m;
v.t ++;
v.ba --;
//if (inrange(v.x,v.y))
if (!vis[v.x][v.y][v.ba][v.en])
{
vis[v.x][v.y][v.ba][v.en] = true;
inc(r);
que[r] = v;
//que[r].f = l;//
}
}
}
}
if (u.en > 0)
{
for (int d=0;d<4;d++)
{
int cost = -1;
v = u;
if (!inrange(u.x+dx[d],u.y+dy[d]) || !wall(u.x+dx[d],u.y+dy[d]))
continue;
do
{
v.x += dx[d];
v.y += dy[d];
cost ++;
}while (inrange(v.x,v.y)&&wall(v.x,v.y)&&cost<=u.en);
if (!inrange(v.x,v.y) || cost > u.en)
continue;
v.en -= cost;
v.t ++;
if (!vis[v.x][v.y][v.ba][v.en])
{
vis[v.x][v.y][v.ba][v.en] = true;
inc(r);
que[r] = v;
}
//que[r].f = l;//
}
}
}
}
int main()
{
//freopen("ou.txt","w",stdout);
while (scanf("%d%d",&n,&m)!=EOF)
{
int sx,sy,tx,ty;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
char tmp;
do tmp = getchar();
while (tmp!='c'&&tmp!='p'&&tmp!='0'&&tmp!='1');
map[i][j] = tmp;
if (tmp == 'c')
{
map[i][j] = '0';
sx = i;
sy = j;
}
else if (tmp == 'p')
{
map[i][j] = '0';
tx = i;
ty = j;
}
}
}
for (int i=1;i<=m;i++)
{
upnear[0][i] = -1;
downnear[n+1][i] = n+1;
}
for (int i=1;i<=n;i++)
{
leftnear[i][0] = -1;
rightnear[i][m+1] = m+1;
for (int j=1;j<=m;j++)
{
if (map[i][j] != '1')
{
leftnear[i][j] = leftnear[i][j-1];
upnear[i][j] = upnear[i-1][j];
}
else
{
leftnear[i][j] = j;
upnear[i][j] = i;
}
}
for (int j=m;j>0;j--)
{
if (map[i][j] != '1')
rightnear[i][j] = rightnear[i][j+1];
else
rightnear[i][j] = j;
}
}
for (int i=n;i>=1;i--)
for (int j=1;j<=m;j++)
{
if (map[i][j] != '1')
downnear[i][j] = downnear[i+1][j];
else
downnear[i][j] = i;
}
/*
printf("Debug\n");
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
printf("%d\t",downnear[i][j]);
}
printf("\n");
}
*/
int ans = bfs(sx,sy,tx,ty);
printf("%d\n",ans);
}
return 0;
}
/**************************************************************
Problem: 1267
User: ssdut_team06
Language: C++
Result: Accepted
Time:2082 ms
Memory:112052 kb
****************************************************************/