code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 5e2 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
bool vis[maxn][maxn][2];
int xx[4] = {0, 0, 1, -1};
int yy[4] = {1, -1, 0, 0};
char mp[maxn][maxn];
struct node{
int x, y, flag, step;
};
bool check(int x, int y){
if(x < 1 || y < 1 || x > n || y > m) return 1;
return 0;
}
queue <node> q;
int bfs()
{
while(!q.empty())
{
node now = q.front();q.pop();
if(mp[now.x][now.y] == 'E') return now.step;
for(int i = 0; i < 4; ++i){
int dx = now.x + xx[i], dy = now.y + yy[i], flag = now.flag;
if(mp[dx][dy] == 'K') flag = 1;
if(check(dx, dy) || vis[dx][dy][flag] || mp[dx][dy] == 'W' || (mp[dx][dy] == 'D' && !flag)) continue;
vis[dx][dy][flag] = 1;
q.push({dx, dy, flag, now.step + 1});
}
}
return -1;
}
void work()
{
cin >> n >> m;
node st;
st.flag = 0, st.step = 0;
for(int i = 1; i <= n; ++i){
cin >> (mp[i] + 1);
for(int j = 1; j <= m; ++j) if(mp[i][j] == 'S') st.x = i, st.y = j;
}
q.push(st);
vis[st.x][st.y][0] = 1;
cout << bfs();
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}
小红的rpg游戏
题意:
一个
n
∗
m
n*m
n∗m 的迷宫,每个位置可能为
∗
*
∗ 墙壁,
.
.
. 空地和怪物(1-9的数字表示血量),初始血量为
h
h
h,消灭怪物会花费响应的血量,当血量
<
=
0
<=0
<=0 则死亡,求左上角到右下角的最短路径。
思路:
这种题目搜索顺序会影响结果
最多不超过
10
10
10 个怪物,因此可以二进制枚举消灭哪些怪物,然后每次
b
f
s
bfs
bfs 维护最短路径
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 50 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m, h;
char mp[maxn][maxn];
bool vis[maxn][maxn], ok[maxn][maxn];
vector <pair<int,int> > v;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
struct node{
int x, y, step;
};
int ans = inf;
bool check(int x, int y){
if(x < 1 || y < 1 || x > n || y > m) return 0;
return 1;
}
void bfs()
{
queue<node> q;
q.push({1, 1});
vis[1][1] = 1;
while(!q.empty())
{
node now = q.front();q.pop();
if(now.x == n && now.y == m){
ans = min(ans, now.step);
return;
}
for(int i = 0; i < 4; ++i){
int xx = now.x + dx[i];
int yy = now.y + dy[i];
if(check(xx, yy) && !vis[xx][yy])
{
if(mp[xx][yy] == '.' || mp[xx][yy] != '*' && ok[xx][yy]){
vis[xx][yy] = 1;
q.push({xx, yy, now.step + 1});
}
}
}
}
}
void work()
{
cin >> n >> m >> h;
for(int i = 1; i <= n; ++i) cin >> (mp[i] + 1);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(mp[i][j] >= '1' && mp[i][j] <= '9')
v.push_back({i, j});
for(int i = 0; i < (1 << v.size()); ++i){
memset(vis, 0, sizeof(vis));
memset(ok, 0, sizeof(ok));
int sum = 0;
for(int j = v.size() - 1; j >= 0; --j) if(i & (1 << j))
ok[v[j].first][v[j].second] = 1, sum += mp[v[j].first][v[j].second] - '0';
if(sum >= h) continue;
bfs();
}
cout << (ans == inf ? -1 : ans);
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}
code1:
这个代码就是比较暴力的思路,类似最短路的更新,然后加一步奇妙的优化
这个优化意思是:斜着走的过程中,我们走到一个点,当前节点无法去更新它的最短路,那么它后边的点也不会被当前点更新最短路
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e3 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int dx[4] = {1, 1, -1, -1};
int dy[4] = {1, -1, 1, -1};
ll dis[maxn][maxn];
int stx, sty, edx, edy;
char mp[maxn][maxn];
struct node{
int x, y, step;
};
bool check(int x, int y){
if(x < 1 || y < 1 || x > n || y > n) return 1;
return 0;
}
void work()
{
mem(dis, 0x3f);
cin >> n >> stx >> sty >> edx >> edy;
for(int i = 1; i <= n; ++i) cin >> (mp[i] + 1);
dis[stx][sty] = 0;
queue <node> q;
q.push({stx, sty, 0});
while(!q.empty()){
node now = q.front();q.pop();
for(int i = 0; i < 4; ++i){
for(int j = 1; j <= n; ++j){
int xx = now.x + j * dx[i], yy = now.y + j * dy[i];
if(check(xx, yy) || mp[xx][yy] == '#') break;
if(dis[xx][yy] > now.step + 1){// 最短路更新
dis[xx][yy] = now.step + 1;
q.push({xx, yy, now.step + 1});
}
else if(dis[xx][yy] < now.step + 1) break;// 奇妙的优化
}
}
}
if(dis[edx][edy] == INF) cout << -1;
else cout << dis[edx][edy];
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}
code2:
01
b
f
s
01bfs
01bfs 写法
开一个三维的
v
i
s
[
x
]
[
y
]
[
o
p
]
vis[x][y][op]
vis[x][y][op] 数组,表示
x
,
y
x,y
x,y 节点是由
o
p
op
op 方向来的
搜索顺序就是由
o
p
op
op 体现的
n
e
x
t
next
next 节点,如果和当前节点方向相同,就不需要花费,否则花费
1
1
1,双端队列维护
如果没有
v
i
s
vis
vis 标记也能卡过去,加上这个标记快到飞起
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e3 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int dx[4] = {1, 1, -1, -1};
int dy[4] = {1, -1, 1, -1};
int dis[maxn][maxn];
int stx, sty, edx, edy;
char mp[maxn][maxn];
bool vis[maxn][maxn][4];
struct node{
int x, y, step, op;
};
bool check(int x, int y){
if(x < 1 || y < 1 || x > n || y > n) return 1;
return 0;
}
void work()
{
mem(dis, 0x3f);
cin >> n >> stx >> sty >> edx >> edy;
for(int i = 1; i <= n; ++i) cin >> (mp[i] + 1);
dis[stx][sty] = 0;
deque <node> q;
q.push_back({stx, sty, 0, -1});
while(!q.empty()){
node now = q.front();q.pop_front();
if(now.x == edx && now.y == edy){
cout << now.step << endl;return;
}
if(now.op != -1){
if(vis[now.x][now.y][now.op]) continue;
vis[now.x][now.y][now.op] = 1;
}
for(int i = 0; i < 4; ++i){
int xx = now.x + dx[i], yy = now.y + dy[i];
if(check(xx, yy) || mp[xx][yy] == '#') continue;
int w = (now.op != i);
if(dis[xx][yy] >= now.step + w){
dis[xx][yy] = now.step + w;
if(w) q.push_back({xx, yy, now.step + 1, i});
else q.push_front({xx, yy, now.step, i});
}
}
}
cout << -1;
}
int main()
{
ios::sync_with_stdio(0);
// int TT;cin>>TT;while(TT--)
work();
return 0;
}