原出處在這裏:DMOJ - CCC '18 S3
這似乎是一個有些冷門的oj。。。
先是看一下題目(翻譯後):
題目背景
機器人Robo在一個工廠裏,偷了很多東西現在要逃出去。
驚了爲什麼我自己程序跑的數據WA了QAQ2333
題目描述
把工廠看爲一個n行m列字符矩陣。
工廠的出口可能在任意一個空地(用 . 表示)上,所以Robo要走所有的空地。Robo從S出發。可能有牆(用W表示),攝像機(用C表示),傳送帶。
攝像機可以拍到它所在行和所在列的狀況(但不能穿牆),Robo不能出現在攝像機視線範圍中,否則就掛了。
Robo不能穿牆,攝像機也不行。Robo只能上下左右移動。
傳送帶有4種:L,R,U,D(左右上下),可能有連續傳送帶,但Robo也可能被永遠卡在傳送帶上?。傳送帶比地面高,所以在上面不會被拍到,但是傳送帶擋不住攝像機視線。
現在請求出,Robo到每個空地的最短步數,傳送帶上不算,如不能到達,輸出-1。
輸入輸出格式
輸入格式:
輸入兩個正整數n,m。
下面n行每行m個字符。
輸出格式:
K行(K表示空地數),每行一個整數表示S到那個點Robo需要的最短步數(不能走到輸出-1),輸出按空地順序(行優先,再列)
對於此題有非常顯然的做法:DFS/BFS,然後我腦抽了竟然用了Dijkstra。。。爲的就是懶得判環了。。。
但這種做法是十分危險的,一定要謹慎:
1.代碼長,方法暴力不好看 (不過看起來倒是很直觀)
2.空間耗得大(不過此題不會MLE)
3.不用堆優化的話時間慢(我還真沒用。。。)不過這個oj速度比較快可以AC。(要是是CCF的老爺機絕對要掛)
有幾個我差點被坑到的地方:我把攝像機視線全設爲牆,但我後來攝像機視線又不能穿牆,導致有地方沒有擋到;還有輸出點的時候應該輸出.的地方不是從第一個點開始。。。
先看容易看懂十分暴力不優美的Dijkstra:(真是喪心病狂)
做好看200+行代碼準備:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int INF=0x7fffffff;
struct edge
{
int to,cost;
};
int fx[4]={1,0,-1,0};
int fy[4]={0,1,0,-1};
int row,col,d[10001],vis[10001],n,spot[10001],count_;
char a[101][101];
bool visit[10001][10001];
vector<edge> graph[10001];
void dijkstra(int s)
{
int min1,k;
for(int i=1;i<=row*col;i++)
d[i]=INF;
d[s]=0;
for(int i=1;i<row*col;i++)
{
min1=INF;
k=s;
for(int j=1;j<=row*col;j++)
if(!vis[j] && min1>d[j])
min1=d[j],k=j;
vis[k]=1;
for(int j=0;j<graph[k].size();j++)
{
int t=graph[k][j].to;
if(!vis[t] && min1+graph[k][j].cost<d[t])
d[t]=min1+graph[k][j].cost;
}
}
return;
}
int main()
{
// freopen("robothief010.in","r",stdin);
// freopen("robothief010.out","w",stdout);
bool flag=true;
int s;
cin>>row>>col;
for(int i=1;i<=row;i++)
for(int j=1;j<=col;j++)
{
cin>>a[i][j];
if(a[i][j]=='.')
n++,spot[count_++]=(i-1)*col+j;
if(a[i][j]=='S')
s=(i-1)*col+j;
}
for(int i=1;i<=row;i++)
for(int j=1;j<=col;j++)
if(a[i][j]=='C')
{
a[i][j]='K';
for(int z=i;z<=row && a[z][j]!='W';z++)
{
if(a[z][j]=='.')
a[z][j]='K';
if(a[z][j]=='S')
{
for(int h=0;h<n;h++)
cout<<"-1"<<endl;
return 0;
}
}
for(int z=i-1;z>=1 && a[z][j]!='W';z--)
{
if(a[z][j]=='.')
a[z][j]='K';
if(a[z][j]=='S')
{
for(int h=0;h<n;h++)
cout<<"-1"<<endl;
return 0;
}
}
for(int z=j+1;z<=col && a[i][z]!='W';z++)
{
if(a[i][z]=='.')
a[i][z]='K';
if(a[i][z]=='S')
{
for(int h=0;h<n;h++)
cout<<"-1"<<endl;
return 0;
}
}
for(int z=j-1;z>=1 && a[i][z]!='W';z--)
{
if(a[i][z]=='.')
a[i][z]='K';
if(a[i][z]=='S')
{
for(int h=0;h<n;h++)
cout<<"-1"<<endl;
return 0;
}
}
}
for(int i=1;i<=row;i++)
for(int j=1;j<=col;j++)
if(a[i][j]=='K')
a[i][j]='W';
edge temp;
for(int i=1;i<=row;i++)
{
for(int j=1;j<=col;j++)
{
if(a[i][j]=='.' || a[i][j]=='S')
{
for(int p=0;p<4;p++)
if(i+fx[p]>=1 && i+fx[p]<=row && j+fy[p]>=1 && j+fy[p]<=col && a[i+fx[p]][j+fy[p]]!='W')
{
if(!visit[(i-1)*col+j][(i+fx[p]-1)*col+j+fy[p]])
{
visit[(i-1)*col+j][(i+fx[p]-1)*col+j+fy[p]]=true;
temp.to=(i+fx[p]-1)*col+j+fy[p];
temp.cost=1;
graph[(i-1)*col+j].push_back(temp);
}
if(!visit[(i+fx[p]-1)*col+j+fy[p]][(i-1)*col+j] && a[i+fx[p]][j+fy[p]]=='.')
{
visit[(i+fx[p]-1)*col+j+fy[p]][(i-1)*col+j]=true;
temp.to=(i-1)*col+j;
temp.cost=1;
graph[(i+fx[p]-1)*col+j+fy[p]].push_back(temp);
}
}
}
else if(a[i][j]!='W' && a[i][j]!='.' && a[i][j]!='S')
{
if(a[i][j]=='L')
{
if(j-1<1 || a[i][j-1]=='W')
{
a[i][j]='W';
continue;
}
if(!visit[(i-1)*col+j][(i-1)*col+j-1])
{
visit[(i-1)*col+j][(i-1)*col+j-1]=true;
temp.to=(i-1)*col+j-1;
temp.cost=0;
graph[(i-1)*col+j].push_back(temp);
}
}
if(a[i][j]=='R')
{
if(j+1>col || a[i][j+1]=='W')
{
a[i][j]='W';
continue;
}
if(!visit[(i-1)*col+j][(i-1)*col+j+1])
{
visit[(i-1)*col+j][(i-1)*col+j+1]=true;
temp.to=(i-1)*col+j+1;
temp.cost=0;
graph[(i-1)*col+j].push_back(temp);
}
}
if(a[i][j]=='D')
{
if(i+1>row || a[i+1][j]=='W')
{
a[i][j]='W';
continue;
}
if(!visit[(i-1)*col+j][(i)*col+j])
{
visit[(i-1)*col+j][(i)*col+j]=true;
temp.to=(i)*col+j;
temp.cost=0;
graph[(i-1)*col+j].push_back(temp);
}
}
if(a[i][j]=='U')
{
if(i-1<1 || a[i-1][j]=='W')
{
a[i][j]='W';
continue;
}
if(!visit[(i-1)*col+j][(i-2)*col+j])
{
visit[(i-1)*col+j][(i-2)*col+j]=true;
temp.to=(i-2)*col+j;
temp.cost=0;
graph[(i-1)*col+j].push_back(temp);
}
}
}
}
}
dijkstra(s);
for(int i=0;i<count_;i++)
{
if(spot[i]==s)
continue;
if(d[spot[i]]==INF)
cout<<"-1"<<endl;
else
cout<<d[spot[i]]<<endl;
}
return 0;
}
OKay,現在是正常的DFS:(由我們學校一位神犇寫的)
(但其實這個代碼是有點問題的,知道錯在哪裏嘛?)
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int n,m,stx,sty;
char map[102][102];
vector<int> endx;
vector<int> endy;
int sht[102][102];
int mapp[102][102]={0};
void dfs(int x,int y,int step)
{
if(mapp[x][y]==1)
return;
if(step>=sht[x][y])
return;
else
sht[x][y]=step;
if(map[x][y]=='L')
{
dfs(x,y-1,step);
return;
}
if(map[x][y]=='R')
{
dfs(x,y+1,step);
return;
}
if(map[x][y]=='U')
{
dfs(x-1,y,step);
return;
}
if(map[x][y]=='D')
{
dfs(x+1,y,step);
return;
}
if(mapp[x+1][y]==0)
dfs(x+1,y,step+1);
if(mapp[x-1][y]==0)
dfs(x-1,y,step+1);
if(mapp[x][y+1]==0)
dfs(x,y+1,step+1);
if(mapp[x][y-1]==0)
dfs(x,y-1,step+1);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='.')
{
endx.push_back(i);
endy.push_back(j);
}
if(map[i][j]=='S')
{
stx=i;
sty=j;
}
if(map[i][j]=='W')
{
mapp[i][j]=1;
}
sht[i][j]=30000;
}
}
for(int i=0;i<=n;i++)
mapp[i][0]=mapp[i][m+1]=1;
for(int i=0;i<=m;i++)
mapp[0][i]=mapp[n+1][i]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(map[i][j]=='C')
{
for(int x=i;x<=n;x++)
{
if(map[x][j]=='W')
break;
else if(map[x][j]=='.')
mapp[x][j]=1;
}
for(int x=i;x>0;x--)
{
if(map[x][j]=='W')
break;
else if(map[x][j]=='.')
mapp[x][j]=1;
}
for(int y=j;y<=m;y++)
{
if(map[i][y]=='W')
break;
else if(map[i][y]=='.')
mapp[i][y]=1;
}
for(int y=j;y>0;y--)
{
if(map[i][y]=='W')
break;
else if(map[i][y]=='.')
mapp[i][y]=1;
}
}
}
}
dfs(stx,sty,0);
for(int i=0;i<endx.size();i++)
{
if(sht[endx[i]][endy[i]]==30000)
cout<<-1<<endl;
else
cout<<sht[endx[i]][endy[i]]<<endl;
}
return 0;
}
接下來是我用BFS又寫了一遍:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N=111;
int n,m;
char a[N][N];
int ans[N][N];
int sx=-1,sy;
const int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
bool checkIn(int x,int y)
{
return 0<=x && x<n && 0<=y && y<m;
}
void input()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s", a[i]);
for(int j=0;j<m;j++)
{
if (a[i][j] == 'S')
sx = i, sy = j;
ans[i][j]=-1;
}
}
}
struct Point
{
int x,y;
Point(int x,int y):x(x),y(y){}
int getAns()const
{
return ans[x][y];
}
char get()const
{
return a[x][y];
}
bool operator<(const Point &p)const
{
if(getAns()!=p.getAns())
return getAns()>p.getAns();
if(x!=p.x)
return x<p.x;
return y<p.y;
}
};
void bfs(int sx,int sy)
{
priority_queue<Point> Q;
ans[sx][sy]=0;
Q.push(Point(sx,sy));
while(!Q.empty())
{
Point u=Q.top();
Q.pop();
int dmin=0,dmax=3;
if (u.get()=='U')
dmin=dmax=0;
else if(u.get()=='D')
dmin=dmax=1;
else if(u.get()=='L')
dmin=dmax=2;
else if(u.get()=='R')
dmin=dmax=3;
for(int d=dmin;d<=dmax;d++)
{
Point v(u.x+dir[d][0],u.y+dir[d][1]);
if(!checkIn(v.x,v.y))
continue;
if(v.get()=='W')
continue;
if(v.get()=='C')
continue;
if(v.getAns()!=-1)
continue;
ans[v.x][v.y]=u.getAns()+(a[v.x][v.y]=='.'?1:0);
Q.push(v);
}
}
}
void solve()
{
bool flag=true;
for(int i=0;i<n && flag;i++)
for(int j=0;j<m && flag;j++)
{
if (a[i][j] == 'C')
for (int d = 0; d < 4 && flag; d++)
for (int x = i, y = j; flag && checkIn(x, y) && a[x][y] != 'W'; x += dir[d][0], y += dir[d][1])
{
if (a[x][y] == '.')
ans[x][y] = -2;
if (a[x][y] == 'S')
flag = false;
}
}
if(!flag)
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
ans[i][j]=-1;
else
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i][j]=='S')
{
bfs(i, j);
break;
}
}
void output()
{
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(a[i][j]=='.')
printf("%d\n",ans[i][j]<0?-1:ans[i][j]);
}
int main()
{
input();
solve();
output();
return 0;
}