题目在这:传送门
分析:A要从(0,0)跑到(m,n)处,地图各个地方有炮台会发射子弹,A必须要不中弹而且能量用完之前到达(m,n),可以的话输出需要的时间,不行就输出Bad luck!
思路:求最短路径用BFS,而这题情况条件比较多,先要多子弹可能会出现的位置和时间做一个预处理,就先标记好,在BFS的时候绕开子弹
AC代码:
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
using namespace std;
bool bu[1000][105][105]; //记录子弹出现情况
bool g[105][105]; //记录碉堡位置
int m,n,k,d;
bool vis[1000][105][105]; //标记该点某时刻是否走过
int dir[][2]= {{1,0},{-1,0},{0,1},{0,-1},{0,0}};
struct castle {
char c;
int t;
int v;
int x,y;
castle(int t=0,int v=0,int x=0,int y=0,char c='N'):t(t),v(v),x(x),y(y),c(c) {}
} cas[105];
struct node { //用一个结构表示某时刻某点
int x,y;
int time; //跑到此点时候所需要的时间
node(int x=0,int y=0,int time=0):x(x),y(y),time(time) {}
};
void pre() { //预处理
memset(bu,false,sizeof(bu));
for(int i=0; i<k; i++) {
int dx=0,dy=0;
switch(cas[i].c) {
case 'N': dx=-1; break;
case 'S': dx=1; break;
case 'W': dy=-1; break;
case 'E': dy=1; break;
}
int nx,ny;
for(int j=1;; j++) { //走到每一步子弹的情况
nx=j*dx+cas[i].x;
ny=j*dy+cas[i].y;
if(nx<0||nx>m||ny<0||ny>n) break;
if(g[nx][ny]) break; //遇到其他堡垒停下来
if(j%cas[i].v==0) { //记录子弹可能存在的位置
for(int h=j/cas[i].v; h<=d; h+=cas[i].t)
bu[h][nx][ny]=true;
}
}
}
}
bool judge(node &nd) { //一个剪枝,判断到达某点时能量与还需要走的最短距离的关系
if(nd.time>d) return false;
int temp=abs(nd.x-m)+abs(nd.y-n);
return d-nd.time>=temp;
}
void bfs() {
memset(vis,false,sizeof(vis));
queue<node>que;
que.push(node(0,0,0));
vis[0][0][0]=true;
while(!que.empty()) {
node p=que.front();
que.pop();
if(p.x==m&&p.y==n) {
printf("%d\n",p.time);
return;
}
for(int i=0; i<5; i++) {
node next=node(p.x+dir[i][0],p.y+dir[i][1],p.time+1);
if(!bu[next.time][next.x][next.y]&&next.x>=0&&next.x<=m&&next.y>=0&&next.y<=n&&!g[next.x][next.y]&&judge(next)&&vis[next.time][next.x][next.y]==0) {
que.push(next); //判断某点是否越界,是否有子弹,是否为堡垒,是否走过
vis[next.time][next.x][next.y]=true;
}
}
}
printf("Bad luck!\n");
}
int main() {
while(scanf("%d%d%d%d",&m,&n,&k,&d)==4) {
getchar();
memset(g,false,sizeof(g));
for(int i=0; i<k; i++) {
scanf("%c",&cas[i].c);
scanf("%d%d%d%d",&cas[i].t,&cas[i].v,&cas[i].x,&cas[i].y);
getchar();
g[cas[i].x][cas[i].y]=true;
}
pre();
bfs();
}
}
小结:一开始数组开太大,超内存,后来开小了还是超出内存,就把一开始用来标记的Int数组全都换成了bool数组,结果就不超时了。。。我也不知道为啥