Battle City(POJ 2312)

问题描述
Battle City(POJ 2312)_第1张图片 
许多人都玩过坦克大战这个游戏,我们现在来考虑一下这个游戏的简化版本: 给出一个地图,这个地图上只有空地,河流,金属墙和砖墙,你的目标是从你当前的位置尽快地获得Bonus(不考虑敌人),如下图: 
 
你的坦克不能穿过河流和墙,但是它可以开炮摧毁砖墙.如果你打中砖墙的话,那个位置就会变成空地.如果你击中了金属墙面,你不会对它造成任何损坏. 
在你行动的每一步,你可以选择移动,或者是不移动而向某个方向开炮,炮弹会向前直行直到击中某一面墙或者飞出地图边界.(显然炮弹比坦克跑得更快) 
现在给出地图,请你找出最少需要行动的步数.
关于输入
输入包含多组数据. 
每组数据第一行包含两个整数m和n(2<=m,n<=300),接下来m行,每行n个字符.'Y'表示你的坦克所在地,'T'表示Bonus的位置,也就是你最后要到达的地方,'S'表示金属墙,'B'表示砖墙,'R'表示河流,'E'表示空地.'Y'和'T'只出现一次. 
输入以两个0表示结束.
关于输出
对每组数据输出一个整数,表示最少行动次数,如果不能到达目标,输出"-1"
例子输入
3 4

YBEB
EERE
SSTE
0 0
例子输出
8
提示

如果你不太明白坦克行动的规则,可以尝试找到这个游戏玩一下:) 
此题的算法实际上更像是Dijkstra,而不是BFS

 

解题思路:

是一个变形的BFS,与普通的BFS相比,它不需要做访问标记,访问过的点还可以二次访问,只是在二次访问的时候,要判断第二次访问时的时间是不是比第一次的时间短,若短,则更新时间值,并继续访问,反之,则不访问;

 

解题代码:

 

#include #include #include #include #include using namespace std; char ss[302][302]; int num[302][302]; int r,c; int a[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; //四个移动方向 struct point { int x; int y; int n; }; bool check(int x1,int y1) //判断是否在矩阵范围内 { if((x1>=0&&x1=0&&y1q; point p,t; int i,temp; p.x=sx; p.y=sy; p.n=0; num[sx][sy]=0; //num[i][j]存储的是终点为(i,j)的最短路径长度,故num[sx][sy]=0 q.push(p); while(!q.empty()) { p=q.front(); q.pop(); for(i=0;i<4;i++) { t.x=p.x+a[i][0]; t.y=p.y+a[i][1]; if(check(t.x,t.y)&&ss[t.x][t.y]!='R'&&ss[t.x][t.y]!='S') //坦克可以移动到该位置 { if(ss[t.x][t.y]=='B') t.n=p.n+2; //该位置字符为'B',故需要加2 else //其他情况加1 t.n=p.n+1; if(num[t.x][t.y]>t.n) //如果以(t.x,t.y)为终点的最小路径长度小于该次的路径长度 { num[t.x][t.y]=t.n; q.push(t); } } } } } int main() { int i,j,bx,by,tx,ty,total; while(scanf("%d%d",&r,&c)!=EOF) { if(r==0&&c==0) break; for(i=0;i

你可能感兴趣的:(算法与数据结构)