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 = 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 nm 的迷宫,每个位置可能为 ∗ * 墙壁, . . . 空地和怪物(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;
}

E. Bishop 2

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值