艰难得A出了这个网上大佬认为得水题,这类题在SDNU见过一次,应该用优先队列来做,因为是以时间优先寻解得,而普通的BFS是以最短路径(贪心)得出解得
但是如何存储我们的路径呢(要求输出路径)并且还要先输出总时间,这就代表,你得先搜完并且得出最优时间,输出时间后,还得一步一步把你存好的路径数出来
正向得输出路径,那就得逆向来搜,用pre存储路径
先来看看准备吧
#include <iostream>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <memory.h>
using namespace std;
int n,m;
struct node{
int x;
int y;
char cc;
int times;
friend bool operator <(node a,node b)
{
return a.times>b.times; //重载小于号,使得时间小的先出队列;
}
}a[105][105],now,nex;
struct Pre{
int px,py;
}pre[105][105];//记录前驱!
int vis[105][105];
int foot[4][2]= {1,0,-1,0,0,1,0,-1};
priority_queue<node> q;
node a[105][105]主要是想用来存储地图(其实浪费了很多,还可以优化得)
now,nex用于bfs搜索
Pre pre[105][105]用来存储路径,因为是倒着走假如从10走到1,那么pre[10] = -1最后输出结束得判断标志
pre[9] = 10; pre[7] = 9——寻求最优解得情况最后pre[1] = 7;
那么你就能从1(起点)开始利用pre数组把路径输出了,注意特判一下终点得时候,详情看代码中
vis数组和foot数组应该很熟悉,只是可能和你起的名不一样
int main()
{
while(scanf("%d%d",&n,&m)!= EOF)
{
getchar();
memset(vis,0,sizeof(vis));
memset(a,0,sizeof(a));
memset(pre,0,sizeof(pre));
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
scanf("%c",&a[i][j].cc);
}
getchar();
}
if(!bfs(n,m))
{
cout<<"God please help our poor hero.\nFINISH"<<endl;
}
}
return 0;
}
输入也挺有讲究得,一定要注意吃不吃空行得问题!!!!请看两个getchar()分别吃了哪里得空行呢?
然后看BFS前期工作
while(!q.empty())q.pop();
pre[x][y].px = -1;
vis[x][y] = 1;
//cout<<"pre[x][y].px = "<<pre[x][y].px<<endl;
now.x = x;
now.y = y;
if(a[x][y].cc == '.')
{
now.times = 0;
}
else if(a[x][y].cc == 'X')
{
return false;
}
else if(a[x][y].cc >= '1' && a[x][y].cc <='9')
{
now.times = a[x][y].cc - '0';
}
q.push(now);
注意清空队列,防止对下一次得输出产生干扰
事先准备
pre[x][y].px = -1;vis[x][y] = 1;
最后有了一个特判最后结束得清况,因为一旦跳到了最后得那一个点我的while寻环就结束了,那终点有怪咋办啊,是吧没输出
而且终点得初始时间也得加上(只考虑有没有怪,不同的代码写法初始时间也不同)
while(!q.empty())
{
now = q.top();
q.pop();
for(int i = 0;i < 4;i++)
{
int nextx = now.x + foot[i][0];
int nexty = now.y + foot[i][1];
if(nextx >= 1 && nextx <= n && nexty >= 1 && nexty <= m && a[nextx][nexty].cc != 'X' && !vis[nextx][nexty])
{
nex.x = nextx;
nex.y = nexty;
vis[nextx][nexty] = 1;
if(a[nextx][nexty].cc == '.')
{
nex.times = now.times + 1;
}
if(a[nextx][nexty].cc >= '1' && a[nextx][nexty].cc <= '9')
{
nex.times = now.times + a[nextx][nexty].cc - '0' + 1;
}
//cout<<nex.times<<endl;
pre[nex.x][nex.y].px = now.x;
pre[nex.x][nex.y].py = now.y;
//printf("pre[%d][%d].px = %d\n",nex.x,nex.y,now.x);
// printf("pre[%d][%d].py = %d\n",nex.x,nex.y,now.y);
q.push(nex);
}
}
}
return false;
}
我觉得这一部分是挺正常得BFS,就是更替入队出对得gu
if(now.x == 1 && now.y == 1)
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n",now.times);
int qq = now.times;
int time = 0;
while(pre[now.x][now.y].px != -1)
{
//cout<<now.x<<endl<<now.y<<endl;
if(a[now.x][now.y].cc == '.')
{
printf("%ds:(%d,%d)->(%d,%d)\n",++time,now.x - 1,now.y - 1,pre[now.x][now.y].px - 1,pre[now.x][now.y].py - 1 );
}
else if(a[now.x][now.y].cc >= '1' && a[now.x][now.y].cc <= '9')
{
int fightt = a[now.x][now.y].cc - '0';
while(fightt--)
{
printf("%ds:FIGHT AT (%d,%d)\n",++time,now.x - 1,now.y - 1);
}
printf("%ds:(%d,%d)->(%d,%d)\n",++time,now.x - 1,now.y - 1 ,pre[now.x][now.y].px - 1,pre[now.x][now.y].py - 1);
}
int t = now.x;
now.x = pre[t][now.y].px;//now.x被你改了!!!!!
now.y = pre[t][now.y].py;
if(now.x == x && now.y == y)
if(a[x][y].cc >= '1' && a[x][y].cc <='9')
{
int tt = a[x][y].cc - '0';
while(tt--)
{
printf("%ds:FIGHT AT (%d,%d)\n",++time,x - 1,y - 1);
}
}
}
printf("FINISH\n");
return true;
}
这一部分就是输出啦,也就是对你前面存储路径思想得实话吧,我的代码最后有个终点得特判输出
加油吧,自己慢慢的写,即使一晚上才弄懂这个题,也是跟着自己的思路走了一遍,而不是直接以别人得思路为起点dfs走一圈,最后
还不一定走的出来,因为会超时得啊~~~