B - Tempter of the Bone
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.
The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
NO
YES
题意:给定时间,问能否从S走到D。
思路:奇偶剪枝,一开始没有看出来,tle了两遍,后来才发现(泪目)
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define N 100
char map[N][N];
int book[N][N];
int n,m,t,sx,sy,ex,ey,flag;
int k[4][2] = {1,0,0,1,-1,0,0,-1};
void dfs(int x,int y,int time)
{
int nx,ny;
//hahaha 奇偶剪枝 !
if(((int)(fabs(x-ex)+fabs(y-ey)))%2 != (t-time)%2||t < time)//如果剩余步数大于剩余时间或者使用时间大于总时间
return ;
if(map[x][y] == 'D'&&t == time)//如果到达终点并且时间严格相等//on exactly the time//认真审题!
{
flag = 1;
return ;
}
for(int i = 0; i < 4; i ++)
{
nx = x + k[i][0];
ny = y + k[i][1];
if(nx<0||ny<0||nx>n-1||ny>m-1||book[nx][ny]||map[nx][ny]=='X')
continue;
book[nx][ny] = 1;
dfs(nx,ny,time+1);
book[nx][ny] = 0;
}
return ;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&t),t!=0||n!=0||m!=0)
{
for(int i = 0; i < n; i ++)
{
scanf("%s",map[i]);
for(int j = 0; j < m; j ++)
{
if(map[i][j] == 'S')
{
sx = i;
sy = j;
}
if(map[i][j] == 'D')
{
ex = i;
ey = j;
}
}
}
memset(book,0,sizeof(book));
flag = 0;
book[sx][sy] = 1;
if((fabs(sx-ex)+fabs(sy-ey))> t)//如果终点到起点的距离大于总时间
{
printf("NO\n");
continue;
}
dfs(sx,sy,0);
if(!flag)//无法到达终点
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
C - Oil Deposits
1 1 * 3 5 *@*@* **@** *@*@* 1 8 @@****@* 5 5 ****@ *@@*@ *@**@ @@@*@ @@**@ 0 0
0 1 2 2
思路:dfs,遍历独立@集的同时全部标记为*.
#include<stdio.h>
#include<string.h>
#define N 100
char map[N+10][N+10];
int n,m;
void dfs(int x,int y)
{
int k[8][2] = {0,1,0,-1,1,0,-1,0,-1,1,1,1,1,-1,-1,-1};
for(int i = 0; i < 8; i ++)
{
int nx = x + k[i][0];
int ny = y + k[i][1];
if(nx < 0||ny < 0||nx > m-1||ny > n-1||map[nx][ny] == '*')
continue;
map[nx][ny] = '*';
dfs(nx,ny);
}
return;
}
int main()
{
int count;
while(scanf("%d%d",&m,&n),m!=0)
{
count = 0;
for(int i = 0; i < m; i ++)
scanf("%s",map[i]);
for(int i = 0; i < m; i ++)
for(int j = 0; j < n; j ++)
if(map[i][j] == '@')
{
map[i][j] = '*';
dfs(i,j);
count ++;
}
printf("%d\n",count);
}
return 0;
}
F - Knight Moves
题意:给定起点和终点的纵坐标、横坐标,按照马走日的走法,问从起点到终点的最小步数(8*8的矩阵)
思路:bfs跑一遍就好了
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
#define N 10
int book[N][N],sx,sy,ex,ey,step;
struct node{
int x,y,step;
};
void bfs()
{
queue<node>q;
struct node now1,start,now2;
int k[8][2] = {-2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2};//马走日坐标
int nx,ny;
start.step = 0;
start.x = sx;
start.y = sy;
q.push(start);
book[sx][sy] = 1;
while(!q.empty())
{
now1 = q.front();
q.pop();
if(now1.x == ex&&now1.y == ey)
{
step = now1.step ;
return;
}
for(int i = 0; i < 8; i ++)
{
nx = now1.x + k[i][0];
ny = now1.y + k[i][1];
if(nx < 1||ny < 1||nx > 8||ny > 8||book[nx][ny])
continue;
now2.x = nx;
now2.y = ny;
now2.step = now1.step + 1;
book[nx][ny] = 1;
if(now2.x == ex&&now2.y == ey)
{
step = now2.step ;
return;
}
q.push(now2);
}
}
return ;
}
int main()
{
char s[N],e[N];
while(scanf("%s%s",s,e)!=EOF)
{
memset(book,0,sizeof(book));
sx = s[1]-'0';
sy = s[0]-'a'+1;
ex = e[1]-'0';
ey = e[0]-'a'+1;
//printf("sx=%d sy=%d ex=%d ey=%d\n",sx,sy,ex,ey);
bfs();
printf("To get from %s to %s takes %d knight moves.\n",s,e,step);
}
return 0;
}
G - Rescue
Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.
Angel's friends want to save Angel. Their task is: approach Angel. We assume that "approach Angel" is to get to the position where Angel stays. When there's a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards.
You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
First line contains two integers stand for N and M.
Then N lines follows, every line has M characters. "." stands for road, "a" stands for Angel, and "r" stands for each of Angel's friend.
Process to the end of the file.
For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing "Poor ANGEL has to stay in the prison all his life."
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
13
思路:优先队列+bfs的简单应用,我记得貌似r不止一个吧,暑假写过,然后被坑惨了,所以这一次还好啦
//stl库中优先队列的应用(暑假写过,被实力坑过,貌似朋友不止一个?)
//默认定义:priority_queue<int>q;
//自定义如下:
#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
#define N 200
char map[N +10][N +10];
int book[N+10][N+10];
int n,m,step;
int sx,sy,flag;
struct node{
int time;
int x,y;
friend bool operator < (struct node a,struct node b)
{
return a.time > b.time ;//time小的优先级高
}//如果a.time>b.time,那么结构体a<b,由于优先队列按照从大到小排,所以b会排在a前面
};
void bfs()
{
struct node start,nowq,nowp;
int k[4][2] = {0,1,0,-1,1,0,-1,0};
int nx,ny,t;
start.time = 0;
start.x = sx;
start.y = sy;
priority_queue<node>q;
q.push(start);
while(!q.empty())
{
nowp = q.top();
// printf("x=%d y=%d step=%d\n",nowp.x ,nowp.y ,nowp.time );
q.pop();
if(map[nowp.x][nowp.y] == 'r')
{
flag = 1;
step = nowp.time ;
return;
}
for(int i = 0; i < 4; i ++)
{
nx = nowp.x + k[i][0];
ny = nowp.y + k[i][1];
if(nx < 0||ny < 0||nx > n-1||ny > m-1||book[nx][ny] == 1||map[nx][ny] == '#')
continue;
nowq.x = nx;
nowq.y = ny;
if(map[nx][ny] == 'x')
nowq.time = nowp.time + 2;
else
nowq.time = nowp.time + 1;
if(map[nowp.x][nowp.y] == 'r')
{
flag = 1;
step = nowp.time ;
return;
}
book[nx][ny] = 1;
q.push(nowq);
}
}
return;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
flag = 0;
for(int i = 0; i < n; i ++)
{
scanf("%s",map[i]);
for(int j = 0; j < m; j ++)
{
if(map[i][j] == 'a')
{
sx = i;
sy = j;
}
}
}
memset(book,0,sizeof(book));
book[sx][sy] = 1;
bfs();
if(!flag)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n",step);
}
return 0;
}
J - Red and Black
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.
Write a program to count the number of black tiles which he can reach by repeating the moves described above.
Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.
There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.
- '.' - a black tile
- '#' - a red tile
- '@' - a man on a black tile(appears exactly once in a data set)
Output
For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).
Sample Input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
Sample Output
59
6
13
题意:问从@开始,能到达的'.'有多少个。
思路:BFS一遍,每一个‘.’点计入总数,输出
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
#define N 20
#define inf 0x3f3f3f3f
char map[N][N];
int book[N][N];
int n,m,sx,sy,step;
struct node{
int x,y;
};
void bfs()
{
queue<node>q;
struct node now1,now2,start;
int k[4][2] = {0,1,0,-1,1,0,-1,0};
int nx,ny;
step = 1;
book[sx][sy] = 1;
start.x = sx;
start.y = sy;
q.push(start);
while(!q.empty())
{
now1 = q.front();
q.pop();
for(int i = 0; i < 4; i ++)
{
nx = now1.x + k[i][0];
ny = now1.y + k[i][1];
if(nx < 0||ny < 0||nx > n-1||ny > m-1||book[nx][ny]||map[nx][ny] == '#')
continue;
book[nx][ny] = 1;
now2.x = nx;
now2.y = ny;
step ++;
q.push(now2);
}
}
}
int main()
{
while(scanf("%d%d",&m,&n),m!=0||n!=0)
{
for(int i = 0; i < n; i ++)
{
scanf("%s",map[i]);
for(int j = 0; j < m; j ++)
{
if(map[i][j] == '@')
{
sx = i;
sy = j;
}
}
}
memset(book,0,sizeof(book));
bfs();
printf("%d\n",step);
}
return 0;
}