洛谷 P3818 小A和uim之大逃離 II
阿新 • • 發佈:2020-11-14
洛谷 P3818 小A和uim之大逃離 II
題目背景
話說上回……還是參見 https://www.luogu.com.cn/problem/P1373 吧
小 a 和 uim 再次來到雨林中探險。突然一陣南風吹來,一片烏雲從南部天邊急湧過來,還伴著一道道閃電,一陣陣雷聲。剎那間,狂風大作,烏雲佈滿了天空,緊接著豆大的雨點從天空中打落下來,只見前方出現了一個牛頭馬面的怪物,低沉著聲音說:“呵呵,既然你們來到這,兩個都別活了!”。小 a 和他的小夥伴再次驚呆了!
題目描述
瞬間,地面上出現了一個 HH 行 WW 列的巨幅矩陣,矩陣的每個格子上要麼是空地 .
或者障礙 #
。
他們起點在 (1,1)(1,1),要逃往 (H,W)(H
這個地方是個是非之地。所以他們希望知道最小能有幾步操作可以離開這個鬼地方。不過他們可能逃不出這個鬼地方,遇到這種情況,只能等死,別無他法。
輸入格式
第一行個整數,H,W,D,RH,W,D,R,意義在描述已經說明。
接下來 HH 行,每行長度是 WW,僅有 .
#
的字串。
輸出格式
請輸出一個整數表示最小的逃出操作次數。如果他們逃不出來,就輸出 -1−1。
題解:
2020.11.14模擬賽T2 95分場。
作法假了...掛了一個點。命好。
我的思路是:裸的走地圖BFS是四種方向搜。這個就變成五種方向就行。
但是假了。為什麼呢?因為喝藥有兩種作用,如果不喝藥能到,喝藥使得步數更少。如果不喝藥到不了,喝藥使穿牆。所以要分兩個部分分別搜尋轉移。
80pts程式碼:
#include<cstdio> #include<queue> using namespace std; const int maxn=1010; int n,m,d,r; char mp[maxn][maxn]; bool vis[maxn][maxn]; int dis[maxn][maxn]; int dx[]={0,0,0,-1,1,0}; int dy[]={0,1,-1,0,0,0}; struct node { int x,y,d; bool f; }; queue<node> q; int main() { // freopen("shadow.in","r",stdin); // freopen("shadow.out","w",stdout); scanf("%d%d%d%d",&n,&m,&d,&r); dx[5]=d; dy[5]=r; for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); if(mp[1][1]=='#') { puts("-1"); return 0; } node a; a.x=1,a.y=1,a.d=0,a.f=0; q.push(a); vis[1][1]=1; while(!q.empty()) { node u=q.front(); q.pop(); if(u.x==n && u.y==m) { printf("%d\n",u.d); return 0; } node v; for(int i=1;i<=5;i++) { v.x=u.x+dx[i]; v.y=u.y+dy[i]; v.d=u.d+1; v.f=u.f; if(v.x<1 || v.y<1 || v.x>n || v.y>m || mp[v.x][v.y]=='#' || vis[v.x][v.y] || (i==5 && v.f)) continue; if(i==5) v.f=1; q.push(v); vis[v.x][v.y]=1; } } puts("-1"); return 0; }
滿分程式碼:
#include <bits/stdc++.h>
#define X x + movx[i]
#define Y y + movy[i]
using namespace std;
bool mapp[2001][2001];
int movx[4] = {1, 0, -1, 0};
int movy[4] = {0, 1, 0, -1};
int n, m;
int a[2001][2001], b[2001][2001];
bool used[2001][2001];
struct hehe{
int x, y;
};
void bfs1()
{
queue < hehe >q;
hehe now;
now.x = now.y = 1;
memset(a, 0x3f, sizeof a);
a[1][1] = 0;
q.push(now);
while(q.size())
{
now = q.front();
q.pop();
int x = now.x, y = now.y;
used[x][y] = 0;
for(int i = 0; i < 4; i++)
{
if(mapp[X][Y] && a[x][y] + 1 < a[X][Y])
{
a[X][Y] = a[x][y] + 1;
if(!used[X][Y])
{
hehe neww;
neww.x = X, neww.y = Y;
q.push(neww);
used[X][Y] = 1;
}
}
}
}
}
void bfs2()
{
queue < hehe >q;
hehe now;
now.x = n;
now.y = m;
memset(b, 0x3f, sizeof b);
memset(used, 0, sizeof used);
b[n][m] = 0;
q.push(now);
while(q.size())
{
now = q.front();
q.pop();
int x = now.x, y = now.y;
used[x][y] = 0;
for(int i = 0; i < 4; i++)
{
if(mapp[X][Y] && b[x][y] + 1 < b[X][Y])
{
b[X][Y] = b[x][y] + 1;
if(!used[X][Y])
{
hehe neww;
neww.x = X, neww.y = Y;
q.push(neww);
used[X][Y] = 1;
}
}
}
}
}
int main()
{
int e, r;
cin >> n >> m >> e >> r;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
char ch;
cin >> ch;
mapp[i][j] = (ch == '.');
}
}
bfs1();
bfs2();
int ans = a[n][m];
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(a[i][j] <= 1000000 && i + e >= 0 && j + r >= 0 && b[i + e][j + r] <= 1000000 && mapp[i + e][j + r])
ans = min(ans, a[i][j] + b[i + e][j + r] + 1);
}
}
if(ans > 1000000 || !mapp[n][m]) cout << -1;
else cout << ans;
return 0;
}