注意点有如下几个:
1.找最短路用bfs遍历;
2.一开始我是用danger结构体记录危险块的物理位置和危险时间,然后每次进行遍历,显然,danger块数∈[1,9999],地图的最大规格是100×100,危险时间∈[0,100],极端情况下最短路径最大会是300【为什么会是300:结合变量的取值范围思考】,也就是最差情况下有4^300个节点,如果每走一个节点都遍历danger块,复杂度就是O(2^600 * 10^4),差不多就是O(10^184)…妥妥超时….所以牺牲空间换时间,用vis数组进行记录每个块是否安全。
3.往常vis数组是二维的,只记录了行数与列数,但是这里又有加时间的维度,所以就是三维数组。同时,vis数组还起到了防止重复访问相同节点的作用(这里的节点的唯一性不仅由位置标出,还与时间有关)
4.看网上的其他题解都是用queue存储,其实可以用priority_queue,优先级改成启发式:当前时间+n-x+m-y【n-x+m-y是当前位置到达n行m列的位置的最短时间】,虽然priority_queue存取比queue慢,但是用了启发式以后还是76ms降到了46ms
代码如下:
//启发式算法 46ms
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<limits.h>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#define iter(i,start,end) for(int (i)=(start);(i)<(end);(i)++)
#define vi vector<int>
using namespace std;
struct danger
{
int x,y,t1,t2;
danger(int a,int b,int c,int d):x(a),y(b),t1(c),t2(d){};
};
struct node
{
int x,y,t;
node(int a,int b,int c):x(a),y(b),t(c){};
};
struct cmp
{
bool operator()(node a ,node b)
{return a.t-a.x-a.y>b.t-b.x-b.y;}
// {return a.t>b.t;}
};
const int nmax=100+5; const int mmax=100+5;
int n,m,t; //n,m \in [1,100] t \in [0,9998]
int kcase;
vector<danger> dangers;
int vis[nmax][mmax][300+5]; //
int xdir[4]={0,-1,0,1}; int ydir[4]={-1,0,1,0};
//← ↑ → ↓
void init();
void solve();
int main()
{
//freopen("201604-4.txt","r",stdin);
kcase=0;
while(scanf("%d %d %d",&n,&m,&t)==3)
{
kcase++;
init();
solve();
}
return 0;
}
bool ok(int i,int j,int t)
{
if(i<0 || i>=n || j<0 || j>=m) return false;
if(vis[i][j][t]==kcase) return false;
return true;
}
void solve()
{
// queue<node> q;
priority_queue<node,vector<node>,cmp> q;
q.push(node(0,0,0)); //【改成启发式算法的话,改下cmp函数就可以了】
vis[0][0][0]=kcase;
while(q.size())
{
node now=q.top();//front();
q.pop();
int x=now.x,y=now.y,time=now.t;
// cout<<"当前正在处理的:("<<x<<","<<y<<","<<time<<")\n";
iter(i,0,4)
{
int newx=x+xdir[i],newy=y+ydir[i];
if(ok(newx,newy,time+1))
{
if(newx==n-1 && newy==m-1 )
{
cout<<time+1<<endl;
return;
}
// cout<<"\t压进点:("<<newx<<","<<newy<<","<<time+1<<")\n";
vis[newx][newy][time+1]=kcase;
q.push(node(newx,newy,time+1));
}
}
}
}
void init()
{
int a,b,c,d;
iter(i,0,t){
cin>>a>>b>>c>>d;
iter(j,c,d+1)
vis[a-1][b-1][j]=kcase;
}