2020牛客寒假算法基础集训营4 G-街机争霸 广搜
G-街机争霸
https://ac.nowcoder.com/acm/contest/4680/G
题解
一道还算正常的广搜题,对于不断移动僵尸,看看数据范围就明白了,移动范围不超过10, 那我们就可以增加一维时间来记录状态mp[x,y,t]表示在(x,y)坐标,t时刻的状态,因为僵尸只移动k步,所以\(2*k-2\) 步之后地图又完全一样了,所以\(t<20\)。把状态确定好之后就直接搜索板子一套就好了。
感想
好久没打过广搜了,一开始竟然觉得深搜也行,心想状态就那么几种。结果连样例都过不了,于是恍然大悟,深搜可不能保证每个状态加入队列一次,因为可能有更短的时间在之后才搜到,然后改成了广搜。样例过了,但是它一直说超过内存限制,这就很迷了。看了半天不知道拿错了,吃完午饭回来,想反正找不出错,不如看看我是不是入队的元素太多了。理论上不会超过\(5*10^6\), 我就加了在代码中加了一条,\(if (Q.size()>5000000) return 0\) , 结果答案错误,那肯定是入队的元素太多了,但是我每个状态都标记了,这就很奇怪了。又想了一会,才发现我是在出队列才标记,如队列没有标记。那肯定会出现重复入队,然后终于AC了,真是悲催。
代码
#include<bits/stdc++.h>
using namespace std;
#define N 510
#define ll long long
const int INF=1e9+7;
int n,m,mo,ans=INF,sx,sy;
char mp1[N][N];
bool mp2[N][N][20];
bool f[N][N][20];
int lx[4]={0,0,-1,1};
int ly[4]={-1,1,0,0};
bool flag=false;
void readChar(char& c){
c=getchar();
while(c!='A' && c!='L' && c!='&' && c!='#') c=getchar();
}
struct Point{int x, y, sum;};
bool dfs(){
int tot=0;
if (mp2[sx][sy][0]==1) return 0;
queue<Point>Q;
Q.push(Point{sx,sy,0});
int x,y,t,sum;
Point u;
while(!Q.empty()){
//cout<<Q.size()<<endl;
u=Q.front(); Q.pop();
x=u.x; y=u.y; t=u.sum%mo; sum=u.sum;
f[x][y][t]=1;
if (mp1[x][y]=='A'){flag=1; ans=min(ans,sum);return 1;}
t=(t+1)%mo;
sum++;
for(int i=0;i<4;i++){
tot++;
int xx=lx[i]+x, yy=ly[i]+y;
if (xx<1 || xx>n || yy<1 || yy>m)continue;
if (mp2[xx][yy][t]) continue;
if (mp1[xx][yy]=='&')continue;
if (f[xx][yy][t])continue;
f[xx][yy][t]=1;
Q.push(Point{xx,yy,sum});
}
}
return 0;
}
void work(){
int num,k;
cin>>n>>m>>num>>k;
mo=2*k-2;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
readChar(mp1[i][j]);
if (mp1[i][j]=='L'){sx=i;sy=j;}
}
for(int i=1;i<=num;i++){
int x,y; string c;
cin>>x>>y>>c;
if (c[0]=='U'){
int t=0;
for(int j=x;t<=k-1;j--,t++)mp2[j][y][t]=1;
for(int j=x-k+2;t<2*k-2;j++,t++)mp2[j][y][t]=1;
}
if (c[0]=='D'){
int t=0;
for(int j=x;t<=k-1;j++,t++)mp2[j][y][t]=1;
for(int j=x+k-2;t<2*k-2;j--,t++)mp2[j][y][t]=1;
}
if (c[0]=='L'){
int t=0;
for(int j=y;t<=k-1;j--,t++)mp2[x][j][t]=1;
for(int j=y-k+2;t<2*k-2;j++,t++)mp2[x][j][t]=1;
}
if (c[0]=='R'){
int t=0;
for(int j=y;t<=k-1;j++,t++)mp2[x][j][t]=1;
for(int j=y+k-2;t<2*k-2;j--,t++)mp2[x][j][t]=1;
}
}
bool flag=dfs();
if (flag)cout<<ans;
else cout<<"Oh no";
}
int main(){
//ios::sync_with_stdio(false);
//cin.tie(0);
work();
}