2018-5-2
其实广搜还是比较容易想到的,但是这道题目相对复杂了一点,需要注意的是:
1)我们可能在那点需要花个时间打个怪兽
2)我们需要记录走过的路径并倒序输出(倒序输出可以用深度优先搜索实现)
#include<iostream>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 100;
char x[N+1][N+1];
int rx[N*N+1],ry[N*N+1];
int m,n;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
struct pre{
int p,q; //pre
int a,b; //now
int c; //cost
}y[N+1][N+1];
bool isvalid(int i,int j){
if (i<0||j<0||i>n-1||j>m-1) return false;
return true;
}
void display(){
if (y[n-1][m-1].c==inf){
cout<<"God please help our poor hero."<<endl;
}
else{
cout<<"It takes "<<y[n-1][m-1].c<<" seconds to reach the target position, let me show you the way."<<endl;
int x1=n-1,x2=m-1,i=1,j;
rx[0]=x1;ry[0]=x2;
while (!(x1==0&&x2==0)){
rx[i]=y[x1][x2].p;
ry[i]=y[x1][x2].q;
x1=rx[i];
x2=ry[i];
i++;
}
int t=1,pp;
for (j=i-1;j>=0;j--){
if (x[rx[j]][ry[j]]=='.'||x[rx[j]][ry[j]]=='X') {
if (j-1>=0) cout<<t<<"s:("<<rx[j]<<","<<ry[j]<<")->"<<"("<<rx[j-1]<<","<<ry[j-1]<<")"<<endl;
t++;
}
else{
pp=x[rx[j]][ry[j]]-'0';
while (pp){
cout<<t<<"s:FIGHT AT ("<<rx[j]<<","<<ry[j]<<")"<<endl;
t++;pp--;
}
if (j-1>=0) cout<<t<<"s:("<<rx[j]<<","<<ry[j]<<")->"<<"("<<rx[j-1]<<","<<ry[j-1]<<")"<<endl;
t++;
}
}
}
cout<<"FINISH"<<endl;
}
void init(){
for (int i=0;i<n;i++){
for (int j=0;j<m;j++){
y[i][j].c=inf;
y[i][j].a=i;
y[i][j].b=j;
}
}
}
void bfs(){
init();
int k,ii,jj;
queue<struct pre>que;
struct pre tmp;
tmp.p=0;tmp.q=0;tmp.a=0;tmp.b=0;tmp.c=0;
que.push(tmp);
while (!que.empty()){
tmp=que.front();
que.pop();
for (k=0;k<4;k++){
ii=tmp.a+dx[k];jj=tmp.b+dy[k];
if (isvalid(ii,jj)&&x[ii][jj]!='X'){
if (x[ii][jj]=='.'){
if (tmp.c+1<y[ii][jj].c){
y[ii][jj].c=tmp.c+1;
y[ii][jj].p=tmp.a;
y[ii][jj].q=tmp.b;
que.push(y[ii][jj]);
}
}else{
if (tmp.c+x[ii][jj]-'0'+1<y[ii][jj].c){
y[ii][jj].c=tmp.c+x[ii][jj]-'0'+1;
y[ii][jj].p=tmp.a;
y[ii][jj].q=tmp.b;
que.push(y[ii][jj]);
}
}
}
}
}
display();
}
int main(){
int i,j;
while (cin>>n>>m){
for (i=0;i<n;i++){
for (j=0;j<m;j++){
cin>>x[i][j];
}
}
bfs();
}
return 0;
}
说一下我的思路:与平时的bfs不同的是,之前只要搜到即是结果,因为我们等同于找到层数最少的,但是这里还可以需要加上打怪兽的时间,我看好多都是用优先队列实现的;还有一个,之前的而言,走过了就不能再走了,但是这里可以还可能往回走,因为我记录了到每一个点所需要的最小值,如果用flag数组标记的话,那么我们就无法更新到达某一个点的花费的最小值了,这里解决的方案是:我们在加入队列时,只有当当前节点被重新更新了,我们才将它放在队列中。反之,我们就没有必要加入进去了。
算法结束时,我们记录的是最短路前驱。