HDU--杭电--1026--Ignatius and the Princess I--广搜--直接暴力0MS,优先队列的一边站 (二)

2014-11-23 21:34:29 · 作者: · 浏览: 13
其关键左右的东西了,简单吧?只要当前点的时间不是0,那就把时间减一再入队,嘿嘿,直到时间为0才可以继续向下走,这就迎合上来题目中的怪物啊,你有多少血,我就陪你入队多少次,你死了,大爷再前进
{
ss.time=time-1;q.push(ss);continue;
}
if(X==0&&Y==0) //到了起点时就可以处理好并结束广搜了
{
if(map[X][Y]>'0'&&map[X][Y]<='9') //因为起点可能也有怪物,所以这个步骤也还是少不得的
up[X][Y].time=map[X][Y]-48;
s=1;return;
}
for(i=0;i<4;i++)
{
x=X+xx[i][0];
y=Y+xx[i][1];
if(x>=0&&y>=0&&x {
visit[x][y]=0;up[x][y].time=up[X][Y].time+1;ss.time=0; //标记为已访问,up内的时间+1,入队的时间初始化为0
if(map[x][y]>'0'&&map[x][y]<='9') //如果是有怪物
up[x][y].time+=map[x][y]-48,ss.time+=map[x][y]-48; //up内的时间再把杀死怪物的时间加上去,入队的时间就记录杀死怪物的时间
up[x][y].x=X;up[x][y].y=Y; //把up内的坐标指向处理好,也就是(x,y)是(X,Y)搜索周围得到的,因此(x,y)要指向(X,Y)
ss.x=x;ss.y=y;q.push(ss); //把入队的坐标处理好并入队
}
}
}
}
int main (void)
{
int i,j,k,l,x,y;
while(cin>>n>>m)
{
for(i=0;i for(j=0;j cin>>map[i][j],visit[i][j]=1,up[i][j].x=up[i][j].y=up[i][j].time=0; //输入map并且初始化up数组还有visit
q=qq;ss.x=n-1;ss.y=m-1;ss.time=0;q.push(ss);s=0;visit[n-1][m-1]=0; //初始化队列,终点的坐标时间打包存入队列并标记它为已访问
if(map[n-1][m-1]>'0'&&map[n-1][m-1]<='9')up[n-1][m-1].time=map[n-1][m-1]-48; //终点如果也有怪物,那么up内的time也要记录
bfs();
if(s)
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n",up[0][0].time); //因为是从尾到首搜索到,所以时间是从尾到首递增,所以总时间是记录在up[0][0]的
i=j=0;l=1; //用i和j从起点回溯,l代表时间
while(i!=n-1||j!=m-1) //一定要用“||”不然可能走到最右边或者最下边就会结束的
{
x=up[i][j].x;y=up[i][j].y;k=up[i][j].time-up[x][y].time-1; //x,y记录下一个点的坐标,k是这点的时间和下一点的时间差减一,因为走一步也要时间的
while(k-->0) //接下来的k分钟就老老实实留在这里打怪好了,哦耶~
printf("%ds:FIGHT AT (%d,%d)\n",l++,i,j);
printf("%ds:(%d,%d)->(%d,%d)\n",l++,i,j,x,y);
i=x;j=y;
}
k=up[i][j].time; //完了之后可没完全完,终点可能是有怪的,所以也要看一看,不然前面就白处理了呗
while(k--)
printf("%ds:FIGHT AT (%d,%d)\n",l++,i,j);
}else puts("God please help our poor hero.");
puts("FINISH");
}
return 0;
}

我是从终点开始向起点广搜的,因为我从一个点搜索周围不可能同时指向四个方向啊,就算可以怎么去区分我要的路线?从起点开始又还要回溯把这条路“打通”懂?本来指向就是单向的,而且还和我要的效果正好相反,多麻烦啊,所以大爷就直接反着搞,省时省力更省心,省省更健康,哦耶~