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
45
59
6
13
这道题就是看最多可以走多少次,#是不可以走的,@是刚开始的位置。这道题就是用的BFS或者DFS进行解题。
BFS一般使用队列进行,用结构体进行存储
方法一:
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int N=22;
bool vis[N][N];
char s[N][N];
int W,H,sx,sy,ans;
int d[4][2]={1,0,-1,0,0,1,0,-1}; //移动,上下左右
struct node{
int x,y;
};
void BFS(int m,int n) //BFS代码
{
node num;
num.x=m,num.y=n;
memset(vis,0,sizeof vis); //每次对vis数组进行初始化
vis[m][n]=1;
queue<node> q;
q.push(num); //入队列
while(!q.empty())
{
node f=q.front();
q.pop();
for(int i=0;i<4;i++)
{
node na;
na.x=f.x+d[i][0];
na.y=f.y+d[i][1];
if(na.x>=0 && na.x<H && na.y>=0 && na.y<W && vis[na.x][na.y]==0 && s[na.x][na.y]!='#') //条件需要注意
{
ans++;
vis[na.x][na.y]=1; //每次走过的都标记一次
q.push(na);
}
}
}
}
int main()
{
while(~scanf("%d %d",&W,&H))
{
if(W==0 && H==0) break;
memset(s,0,sizeof s);
for(int i=0;i<H;i++) scanf("%s",s[i]);
for(int i=0;i<H;i++)
{
for(int j=0;j<W;j++)
{
if(s[i][j]=='@') //这里判断,因为只有一个@,所以只要找到这个@的坐标就可以break退出循环
{
sx=i;
sy=j;
break;
}
}
}
ans=0;
BFS(sx,sy);
printf("%d\n",ans+1); //最后需要加1,因为@那个也算一步,所以需要加上最开始的1.
}
return 0;
}
方法二:
DFS采用的是回溯,也是递归的一种。一般不需要利用结构体。
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=50;
char s[N][N];
bool vis[N][N];
int d[4][2]={1,0,-1,0,0,1,0,-1};
int W,H,sx,sy,ans,dx,dy;
void DFS(int a,int b){
vis[a][b]=1;
ans++;
for(int i=0;i<4;i++)
{
dx=a+d[i][0];
dy=b+d[i][1];
if(dx>=0 && dx<H && dy>=0 && dy<W && vis[dx][dy]==0 && s[dx][dy]!='#')
{
vis[dx][dy]=1;
DFS(dx,dy);
}
}
}
int main()
{
while(~scanf("%d %d",&W,&H) && (W||H))
{
memset(s,0,sizeof s);
memset(vis,0,sizeof vis);
for(int i=0;i<H;i++) scanf("%s",s[i]);
for(int i=0;i<H;i++)
for(int j=0;j<W;j++)
{
if(s[i][j]=='@')
{
sx=i;
sy=j;
break;
}
}
ans=0;
DFS(sx,sy);
printf("%d\n",ans);
}
return 0;
}
BFS(宽度优先搜索)一般解决最少步数的解,遇到的解一定是一个最优解,BFS是舍去空间换时间
DFS (深度优先搜索) 一般解决的全部的解,采用的回溯,DFS是舍去时间换空间。
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.)
Input
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.
Output
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.”
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
r代表的是a的朋友,x是警卫,“#”是墙不可以走,“。”是路,r可以从警卫旁走,但是消耗的时间需要加1,求r到a的最短时间。
这道题的坑在于朋友是不止一个的,他可能有多个朋友,所以如果从r到a的结果可能需要计算许多次,所以需要反过来进行,让a来找r,找到第一个r就可以停止了
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int N=210;
bool vis[N][N];
char s[N][N];
int d[4][2]={1,0,-1,0,0,1,0,-1};
int a,b,sx,sy;
struct node
{
int x,y,step;
};
int BFS(int m,int n) //直接套BFS模板
{
node num;
vis[m][n]=1;
num.x=m,num.y=n,num.step=0;
queue<node> q; //其实是需要用优先队列的,但是用队列的话,也过了
q.push(num);
while(!q.empty())
{
node f=q.front();
q.pop();
for(int i=0;i<4;i++)
{
node nx;
nx.x=f.x+d[i][0];
nx.y=f.y+d[i][1];
nx.step=f.step+1;
if(nx.x>=0 && nx.x<a && nx.y>=0 && nx.y<b && vis[nx.x][nx.y]==0 && s[nx.x][nx.y]!='#') //判断是否越界
{
if(s[nx.x][nx.y]=='x') nx.step+=1; //如果碰到警卫,时间需要加1
if(s[nx.x][nx.y]=='r') return nx.step;
vis[nx.x][nx.y]=1;
q.push(nx); //每次把nx放入队列中
}
}
}
return -1; //如果没有的话,返回-1
}
int main()
{
while(~scanf("%d %d",&a,&b))
{
memset(s,0,sizeof s);
memset(vis,0,sizeof vis);
for(int i=0;i<a;i++) scanf("%s",s[i]);
for(int i=0;i<a;i++)
for(int j=0;j<b;j++)
{
if(s[i][j]=='a')
{
sx=i,sy=j;
break;
}
}
int k=BFS(sx,sy);
if(k==-1) printf("Poor ANGEL has to stay in the prison all his life.\n");
else printf("%d\n",k);
}
return 0;
}
Battle City
Your tank can’t move through rivers or walls, but it can destroy brick walls by shooting. A brick wall will be turned into empty spaces when you hit it, however, if your shot hit a steel wall, there will be no damage to the wall. In each of your turns, you can choose to move to a neighboring (4 directions, not 8) empty space, or shoot in one of the four directions without a move. The shot will go ahead in that direction, until it go out of the map or hit a wall. If the shot hits a brick wall, the wall will disappear (i.e., in this turn). Well, given the description of a map, the positions of your tank and the target, how many turns will you take at least to arrive there?
Input
The input consists of several test cases. The first line of each test case contains two integers M and N (2 <= M, N <= 300). Each of the following M lines contains N uppercase letters, each of which is one of ‘Y’ (you), ‘T’ (target), ‘S’ (steel wall), ‘B’ (brick wall), ‘R’ (river) and ‘E’ (empty space). Both ‘Y’ and ‘T’ appear only once. A test case of M = N = 0 indicates the end of input, and should not be processed.
Output
For each test case, please output the turns you take at least in a separate line. If you can’t arrive at the target, output “-1” instead.
Sample Input
3 4
YBEB
EERE
SSTE
0 0
Sample Output
8
Y是初始位置,T是目标位置,S是钢墙,不能穿过,E是路,R是小溪不可以过,B是砖墙,可以打碎,但是时间需要消耗1,看最短时间是多少
这里需要用到优先队列,每次找出时间最短的那条路
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int N=310;
int vis[N][N];
char s[N][N];
int n,m,sx,sy;
int d[4][2]={1,0,-1,0,0,1,0,-1};
struct node
{
int x,y;
int step;
bool operator <(const node &a) const //重载小于号,也可以用greater来定义优先队列
{
return step>a.step;
}
};
bool search(int a,int b) //判断是否越界
{
if(a>=0 && a<n && b>=0 && b<m && vis[a][b]==0 && s[a][b]!='S' && s[a][b]!='R')
return true;
else
return false;
}
int bfs()
{
priority_queue<node> q;
vis[sx][sy]=1;
node num;
num.x=sx,num.y=sy,num.step=0;
q.push(num);
while(!q.empty())
{
node f=q.top();
q.pop();
for(int i=0;i<4;i++)
{
node nx;
nx.x=f.x+d[i][0];
nx.y=f.y+d[i][1];
nx.step=f.step+1;
if(search(nx.x,nx.y))
{
if(s[nx.x][nx.y]=='B') nx.step++;
if(s[nx.x][nx.y]=='T') return nx.step;
vis[nx.x][nx.y]=1;
q.push(nx);
}
}
}
return -1;
}
int main()
{
while(~scanf("%d %d",&n,&m) && (n||m))
{
memset(vis,0,sizeof vis);
for(int i=0;i<n;i++) scanf("%s",s[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(s[i][j]=='Y')
{
sx=i,sy=j;
break;
}
}
int k=bfs();
printf("%d\n",k);
}
return 0;
}
Dungeon Master
You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of unit cubes which may or may not be filled with rock. It takes one minute to move one unit north, south, east, west, up or down. You cannot move diagonally and the maze is surrounded by solid rock on all sides.
Input
The input consists of a number of dungeons. Each dungeon description starts with a line containing three integers L, R and C (all limited to 30 in size).
L is the number of levels making up the dungeon.
R and C are the number of rows and columns making up the plan of each level.
Then there will follow L blocks of R lines each containing C characters. Each character describes one cell of the dungeon. A cell full of rock is indicated by a ‘#’ and empty cells are represented by a ‘.’. Your starting position is indicated by ‘S’ and the exit by the letter ‘E’. There’s a single blank line after each level. Input is terminated by three zeroes for L, R and C.
Output
Each maze generates one line of output. If it is possible to reach the exit, print a line of the form
Escaped in x minute(s).
where x is replaced by the shortest time it takes to escape.
If it is not possible to escape, print the line
Trapped!
Sample Input
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0
Sample Output
Escaped in 11 minute(s).
Trapped!
这题是有六个方向进行移动,判断能否从S移动到E,如果可以的话,就输出Escaped in x minute(s). 其中x是时间,如果不行的话,输出Trapped!
这道题还是模板题,只是移动的方向多了上下,对结构体多加了一个元素
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int N=35;
bool vis[N][N][N];
char s[N][N][N];
int d[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
int L,R,C,sx,sy,sz;
struct node{
int x,y,z,step;
};
int BFS()
{
memset(vis,0,sizeof vis);
queue<node> q;
node num;
num.x=sx,num.y=sy,num.z=sz,num.step=0;
vis[num.x][num.y][num.z]=1;
q.push(num);
while(!q.empty())
{
node f=q.front();
q.pop();
for(int i=0;i<6;i++)
{
node nx;
nx.x=f.x+d[i][0];
nx.y=f.y+d[i][1];
nx.z=f.z+d[i][2];
nx.step=f.step+1;
if(nx.x>=0 && nx.x<L && nx.y>=0 && nx.y<R && nx.z>=0 && nx.z<C && s[nx.x][nx.y][nx.z]!='#' && vis[nx.x][nx.y][nx.z]==0)
{
if(s[nx.x][nx.y][nx.z]=='E') return nx.step;
vis[nx.x][nx.y][nx.z]=1;
q.push(nx);
}
}
}
return -1;
}
int main()
{
while(~scanf("%d %d %d",&L,&R,&C))
{
if(L==0 && R==0 && C==0) break;
for(int i=0;i<L;i++)
for(int j=0;j<R;j++)
{
scanf("%s",s[i][j]);
for(int k=0;k<C;k++)
{
if(s[i][j][k]=='S')
{
sx=i;
sy=j;
sz=k;
}
}
}
int k=BFS();
if(k==-1) printf("Trapped!\n");
else printf("Escaped in %d minute(s).\n",k);
}
return 0;
}
Catch That Cow
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Input
Line 1: Two space-separated integers: N and K
Output
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
Sample Input
5 17
Sample Output
4
从N到K,每次可以选择走到N+1或者N-1,或者2*N,计算几步走到K
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
const int M = 100001;
int N,K,ans;
bool vis[M];
struct node{
int x;
int step;
};
int main(){
scanf("%d%d",&N,&K);
node num;
num.x=N;num.step=0;
memset(vis,0,sizeof(vis));
vis[N]=1;
queue<node>q;
q.push(num);
while(!q.empty()){
node f=q.front();
q.pop();
for(int i=0;i<3;i++){ //针对不同的情况进行判断
node nx;
if(i==0) nx.x=f.x+1;
else if(i==1) nx.x=f.x-1;
else nx.x=f.x*2;
nx.step=f.step+1;
if(nx.x>=0 && nx.x<=M && vis[nx.x] == 0 ){
if(nx.x==K) ans=nx.step;
vis[nx.x] = 1;
q.push(nx);
}
}
}
printf("%d\n",ans);
}