bfs一入不回头

bfs与优化

前言:

这玩意比深搜好多了好吗

深搜是真的恶心人


1. 电路维修(打开灯泡)

/*
  Time: 12.27
  Worker: Blank_space
  Source: #2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On
*/
/*--------------------------------------------*/
#include<cstdio>
#include<queue>
#include<iostream>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, m, dis[C];
struct edge{
	int v ,w, nxt;
}e[C];
int head[C], js;
bool vis[C];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
void add_edge(int u, int v, int w)
{
	e[++js].v = v; 
	e[js].w = w;
	e[js].nxt = head[u];
	head[u] = js;
}
/*----------------------------------------函数*/
int main()
{
    n = read(); m = read();
    for(int i = 1; i <= n; i++)
    	for(int j = 1; j <= m; j++)
    	{
    		char s; bool p = 0;	cin >> s;
    		if(s == '/') p = 1;
    		add_edge((i - 1) * (m + 1) + j, i * (m + 1) + j + 1, p);
    		add_edge(i * (m + 1) + j + 1, (i - 1) * (m + 1) + j, p);
    		add_edge((i - 1) * (m + 1) + j + 1, i * (m + 1) + j, p ^ 1);
    		add_edge(i * (m + 1) + j, (i - 1) * (m + 1) + j + 1, p ^ 1);
    	}
    for(int i = 1; i <= n * m + n + m + 1; i++) dis[i] = INF;
	deque <int> q;
    q.push_back(1); dis[1] = 0;// vis[1] = 1;
    while(!q.empty())
    {
    	int u = q.front();
    	q.pop_front();
    	if(vis[u]) continue;
    	vis[u] = 1;
    	for(int i = head[u]; i; i = e[i].nxt)
    	{
    		int v = e[i].v, w = e[i].w;
    		dis[v] = min(dis[v], dis[u] + w);
    		if(w) q.push_back(v);
    		else q.push_front(v);
    	}
    }
    if(dis[(m + 1) * (n + 1)] == INF) puts("NO SOLUTION");
    else printf("%d", dis[(m + 1) * (n + 1)]);
	return 0;
}

2. 魔板

/*
  Time: 12.27
  Worker: Blank_space
  Source: #10027. 「一本通 1.4 例 2」魔板
  按照自己的思路写的 以每种情况作为一种状态 map映射
*/
/*--------------------------------------------*/
#include<cstdio>
#include<iostream>
#include<map>
#include<queue>
#include<string>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int E = 12345678;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int a[10];
map <int, int> dis;
map <int, string> path;
queue <int> q;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
int g()
{
	int sum = 0;
	for(int i = 1; i <= 8; i++) sum = sum * 10 + a[i];
	return sum;
}
void change(int opt)
{
	if(opt == 1)
		for(int i = 1; i <= 4; i++) swap(a[i], a[9 - i]);
	if(opt == 2)
	{
		int x = a[4], y = a[5];
		for(int i = 3; i >= 1; i--) a[i + 1] = a[i];
		for(int i = 5; i <= 7; i++) a[i] = a[i + 1];
		a[1] = x; a[8] = y;
	}
	if(opt == 3)
	{
		int x = a[7];
		a[7] = a[6];
		a[6] = a[3];
		a[3] = a[2];
		a[2] = x;
	}
	if(opt == 4)
	{
		int x = a[1], y = a[8];
		for(int i = 1; i <= 3; i++) a[i] = a[i + 1];
		for(int i = 7; i >= 5; i--) a[i + 1] = a[i];
		a[4] = x; a[5] = y;
	}
	if(opt == 5)
	{
		int x = a[7];
		a[7] = a[2];
		a[2] = a[3];
		a[3] = a[6];
		a[6] = x;
	}
}
void cover(int x)
{
	for(int i = 8; i >= 1; i--)
	{
		a[i] = x % 10;
		x /= 10;
	}
}
/*----------------------------------------函数*/
int main()
{
    for(int i = 1; i <= 8; i++) a[i] = read();
    int n = g();
    q.push(E);
    while(!q.empty())
    {
    	int u = q.front();
    	q.pop();
    	if(u == n) break;
    	cover(u);
    	for(int i = 1; i <= 3; i++)
    	{
    		change(i);
    		int v = g();
    		if(!dis.count(v))
    		{
    			dis[v] = dis[u] + 1;
    			q.push(v);
    			string s1 = path[u];
    			if(i == 1) s1 += 'A';
    			if(i == 2) s1 += 'B';
    			if(i == 3) s1 += 'C';
    			path[v] = s1;
    		}
    		change(i != 1 ? i + 2 : 1);
    	}
    }
    printf("%d\n", dis[n]);
    cout << path[n];
	return 0;
}

3. Knight Moves

/*
  Time: 12.27
  Worker: Blank_space
  Source: #10028. 「一本通 1.4 例 3」Knight Moves
*/
/*--------------------------------------------*/
#include<cstdio>
#include<queue>
#include<string.h>
#define emm(x) memset(x, 0, sizeof x)
using namespace std; 
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int T, m, sx, sy, tx, ty;
int dx[9] = {0, 1, 1, -1, -1, 2, 2, -2, -2};
int dy[9] = {0, 2, -2, 2, -2, 1, -1, 1, -1};
struct node {
	int x, y;
};
queue <node> q1;
queue <node> q2;
int vis1[310][310], vis2[310][310];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
void clear1()
{
	queue <node> q;
	swap(q, q1);
}
void clear2()
{
	queue <node> q;
	swap(q, q2);
}
void work()
{
	emm(vis1); emm(vis2); clear1(); clear2();
	m = read(); sx = read(); sy = read(); tx = read(); ty = read();
	if(sx == tx && sy == ty) {puts("0"); return ;}
	q1.push((node){sx, sy}); q2.push((node){tx, ty});
	while(!q1.empty() && !q2.empty())
	{
		if(q1.size() <= q2.size() || q2.empty())
		{
			node t = q1.front(); q1.pop();
			int x = t.x, y = t.y;
			for(int i = 1; i <= 8; i++)
			{
				int xx = x + dx[i], yy = y + dy[i];
				if(xx < 0 || xx > m || yy < 0 || yy > m || vis1[xx][yy]) continue;
				vis1[xx][yy] = vis1[x][y] + 1;
				if(vis2[xx][yy]) {printf("%d\n", vis1[xx][yy] + vis2[xx][yy]); return ;}
				q1.push((node){xx, yy});
			}
			continue;
		}
		if(q1.size() >  q2.size() || q1.empty())
		{
			node t = q2.front(); q2.pop();
			int x = t.x, y = t.y;
			for(int i = 1; i <= 8; i++)
			{
				int xx = x + dx[i], yy = y + dy[i];
				if(xx < 0 || xx > m || yy < 0 || yy > m || vis2[xx][yy]) continue;
				vis2[xx][yy] = vis2[x][y] + 1;
				if(vis1[xx][yy]) {printf("%d\n", vis1[xx][yy] + vis2[xx][yy]); return ;}
				q2.push((node){xx, yy});
			}
			continue;
		}
	}
}
/*----------------------------------------函数*/
int main()
{
    T = read();
    while(T--) work();
	return 0;
}

4. 棋盘游戏

/*
  Time: 12.27
  Worker: Blank_space
  Source: #10029. 「一本通 1.4 练习 1」棋盘游戏
  感觉这个题可以看做直接将不同的棋子移到对应位置 试一下
  80 Pts
  这样做是可以的 但是有一点bug:
  一个棋子先搜到一个自己位置可能会占用其他棋子的最优位置 导致答案不是最优
  手动改变一下搜索顺序 从外圈开始搜 100 Pts
*/
/*--------------------------------------------*/
#include<cstdio>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int mp1[5][5], mp2[5][5], ans;
struct node {
	int x, y;
};
int dx[5] = {0, 1, -1, 0, 0};
int dy[5] = {0, 0, 0, 1, -1};
bool vis[5][5];
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
void bfs(int x, int y)
{
	queue <node> q;
	q.push((node){x, y});
	while(!q.empty())
	{
		node h = q.front(); q.pop();
		int _x = h.x, _y = h.y;
		for(int i = 1; i <= 4; i++)
		{
			int xx = _x + dx[i], yy = _y + dy[i];
			if(xx < 1 || xx > 4 || yy < 1 || yy > 4) continue;
			if(!vis[xx][yy] && mp2[xx][yy])
			{
				ans += abs(xx - x) + abs(yy - y);
				vis[xx][yy] = 1; return ;
			}
			q.push((node){xx, yy});
		}
	}
}
/*----------------------------------------函数*/
int main()
{
    for(int i = 1; i <= 4; i++)
    	for(int j = 1; j <= 4; j++)
    	{
    		char c; cin >> c;
    		mp1[i][j] = c - 48;
    	}
    for(int i = 1; i <= 4; i++)
    	for(int j = 1; j <= 4; j++)
		{
			char c; cin >> c;
			mp2[i][j] = c - 48;
			if(mp1[i][j] == mp2[i][j]) vis[i][j] = 1;
		}
	for(int i = 1; i <= 4; i++) if(mp1[1][i] > mp2[1][i]) bfs(1, i);
	for(int i = 1; i <= 4; i++) if(mp1[4][i] > mp2[4][i]) bfs(4, i);
	for(int i = 1; i <= 4; i++) if(mp1[2][i] > mp2[2][i]) bfs(2, i);
	for(int i = 1; i <= 4; i++) if(mp1[3][i] > mp2[3][i]) bfs(3, i);
    printf("%d", ans);
	return 0;
}

5. Keyboarding

没做

6. 山峰和山谷

/*
  Time: 12.27
  Worker: Blank_space
  Source: #2653. 「POI2007」山峰和山谷 Ridges and Valleys
  看一下数据范围 dfs大概要挂  还是bfs
  似乎挂了 83Pts
  加个优化 78Pts ... ???
  再调一下 
*/
/*--------------------------------------------*/
#include<cstdio>
#include<string.h>
#include<queue>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, mp[1010][1010], ans1, ans2;
bool vis[1010][1010];
struct node {
	int x, y;
};
int dx[9] = {0, 0, 0, 1, 1, 1, -1, -1, -1};
int dy[9] = {0, 1, -1, 0, 1, -1, 0, 1, -1};
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/
void bfs(int x, int y)
{
	queue <node> q;
	q.push((node){x, y});
	int g1 = 1, d = 0;// 1 周围低于中间  2 高
	while(!q.empty())
	{
		node h = q.front(); q.pop();
		int _x = h.x, _y = h.y;
		for(int i = 1; i <= 8; i++)
		{
			int xx = _x + dx[i], yy = _y + dy[i];
			if(xx < 1 || xx > n || yy < 1 || yy > n) continue;
			if(mp[xx][yy] == mp[_x][_y] && !vis[xx][yy]) q.push((node){xx, yy}), vis[xx][yy] = 1;
			if(d == 0)
				d = mp[xx][yy] < mp[_x][_y] ? 1 : mp[xx][yy] > mp[_x][_y] ? 2 : 0;
			else if(!g1) continue;
			else if(mp[xx][yy] > mp[_x][_y] && d == 1) g1 = 0;
			else if(mp[xx][yy] < mp[_x][_y] && d == 2) g1 = 0;
		}
	}
	if(d == 1) ans1 += g1;
	if(d == 2) ans2 += g1;
	if(d == 0) ans1 = 1, ans2 = 1;
}
/*----------------------------------------函数*/
int main()
{
    n = read();
    for(int i = 1; i <= n; i++)
    	for(int j = 1; j <= n; j++) mp[i][j] = read();
    for(int i = 1; i <= n; i++)
    	for(int j = 1; j <= n; j++)
    		if(!vis[i][j])
				bfs(i, j);
	printf("%d %d", ans1, ans2);
	return 0;
}

上一篇:Codeforces Round #688 (Div. 2) C. Triangles(思维,数学)


下一篇:Postgresql 导入导出/创建库等基本使用小记,一看就懂,一学就会!