title: NEU_Train_Camp_2020_搜索和简单图论
date: 2020-07-05 22:38:11
tags:
- c++
categories: - New
cover:
搜索和简单图论
A - Knight Moves
HDU 1372
每组数据输入两个坐标,(a-h)代表列,(1-8)代表行,得出Knight Move的最小步数
国际象棋中Knight和中国象棋中马的走法一致,有八个落点.
标准的,最简单的BFS
#include <bits/stdc++.h>
using namespace std;
int dir[8][2] = {{1, -2}, {2, -1}, {2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}};
bool vis[10][10] = {false}; // 记录点是曾经被加入队列
#define mp(a, b) make_pair(a, b)
int bfs(int sx, int sy, int tx, int ty)
{
memset(vis, 0, sizeof(vis));
queue<pair<int, pair<int, int>>> que; //步数,<x,y>
vis[sx][sy] = true;
que.push(mp(0, mp(sx, sy)));
while (!que.empty())
{
pair<int, pair<int, int>> now = que.front();
que.pop();
if (now.second.first == tx and now.second.second == ty)
{
return now.first;
}
for (int i = 0; i < 8; i++)
{
int x = now.second.first + dir[i][0];
int y = now.second.second + dir[i][1];
if (x >= 1 and x <= 8 and y >= 1 and y <= 8)
{
if (!vis[x][y])
{
vis[x][y] = true;
que.push(mp(now.first + 1, mp(x, y)));
}
}
}
}
return -1;
}
int main(void)
{
char a, b, c, d;
while (cin >> a >> b >> c >> d)
{
printf("To get from %c%c to %c%c takes %d knight moves.
", a, b, c, d, bfs(a - 'a' + 1, b - '0', c - 'a' + 1, d - '0'));
}
return 0;
}
B - Sorting It All Out
POJ 1094
每行两个正整数,n,m. 2 <= n <= 26 ,要排序的是前n个大写字母,接下来m行,用<
表示两个字母的排序关系.
输出
Sorted sequence determined after xxx relations: yyy...y. //在给定x个关系后,得出符合要求的排列
Sorted sequence cannot be determined. //排序不唯一
Inconsistency found after xxx relations. //条件矛盾,既有向图成环
字母有序排列,形成有向图,进行拓扑排序,判断是否有环,得出解.
同 [软件依赖] (something)
#include <vector>
#include <iostream>
#include <string>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
vector<int> edge[30];
int indegree[30] = {0};
int n, m;
string ans;
//0 成环 , 1 唯一解 ,2 不确定
int topoSort()
{
int temp[30];
copy(indegree, indegree + 30, temp);
ans.clear();
queue<int> que;
int flag = 1;
for (int i = 0; i < n; i++)
{
if (!indegree[i])
{
que.push(i);
}
}
ans.clear();
while (!que.empty())
{
if (que.size() > 1)
flag = 2;
int now = que.front();
que.pop();
ans.push_back(now + 'A');
for (int i = 0; i < edge[now].size(); i++)
{
if (--temp[edge[now][i]] == 0)
{
que.push(edge[now][i]);
}
}
}
if (ans.size() != n)
flag = 0;
return flag;
}
inline int num(char a)
{
return a - 'A';
}
int main(void)
{
while (cin >> n >> m and (n or m))
{
memset(indegree, 0, sizeof(indegree));
for (int i = 0; i < 30; i++)
{
edge[i].clear();
}
bool done = false;
int res;
for (int i = 0; i < m; i++)
{
char a, b, c;
cin >> a >> b >> c;
if (done)
continue;
edge[num(a)].push_back(num(c));
indegree[num(c)]++;
res = topoSort();
if (res == 0)
{
done = true;
cout << "Inconsistency found after " << i + 1 << " relations." << endl;
}
else if (res == 1)
{
done = true;
cout << "Sorted sequence determined after " << i + 1 << " relations: ";
// for (auto &&j : ans)
cout << ans;
cout << ".
";
}
}
if (res == 2)
{
cout << "Sorted sequence cannot be determined." << endl;
}
}
return 0;
}
C - Eight
HDU 1043
题意描述:给出一个3×3的矩阵(包含1~8数字和一个字母x),经过一些移动格子上的数后得到连续的1~8,最后一格是x,要求最小移动步数,输出走法。
难点在于将这个矩阵hash,使用unordered_set会MLE,这里使用的是康托展开.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stdlib.h>
#include <cctype>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define mem(a, x) memset(a, x, sizeof(a))
using namespace std;
typedef long long ll;
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1}; //上下左右
const char dd[] = "durl";
const int ans = 46234; //123456780
int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int ct(int s[])
{
int sun = 0, tmp;
for (int i = 0; i < 9; i++)
{
tmp = 0;
for (int j = i + 1; j < 9; j++)
if (s[j] < s[i])
tmp++;
sun += (tmp * fac[9 - i - 1]);
}
return sun + 1;
}
struct Node
{
int g[10];
int x;
int st;
} h;
struct No
{
int fa;
char mo;
} moo[400000];
bool vis[400000];
void bfs()
{
queue<Node> q;
q.push(h);
vis[h.st] = 1;
while (!q.empty())
{
h = q.front();
q.pop();
int x = h.x / 3;
int y = h.x % 3;
for (int i = 0; i < 4; ++i)
{
int xx = x + dx[i];
int yy = y + dy[i];
if (xx >= 0 && yy >= 0 && xx < 3 && yy < 3)
{
Node nx = h;
nx.x = xx * 3 + yy;
swap(nx.g[h.x], nx.g[nx.x]);
nx.st = ct(nx.g);
if (!vis[nx.st])
{
vis[nx.st] = 1;
moo[nx.st].mo = dd[i];
moo[nx.st].fa = h.st;
q.push(nx);
}
}
}
}
}
void init()
{
for (int i = 0; i < 8; ++i)
h.g[i] = i + 1;
h.g[8] = 0;
h.x = 8;
h.st = ans;
moo[ans].fa = -1;
bfs();
}
int main()
{
char tmp;
init();
int s[10];
while (cin >> tmp)
{
if (tmp == 'x')
s[0] = 0;
else
s[0] = tmp - 48;
for (int i = 1; i < 9; ++i)
{
cin >> tmp;
if (tmp == 'x')
s[i] = 0;
else
s[i] = tmp - 48;
}
int st = ct(s);
if (st == ans)
{
puts("");
continue;
}
if (!vis[st])
printf("unsolvable
");
else
{
while (moo[st].fa != -1)
{
printf("%c", moo[st].mo);
st = moo[st].fa;
}
puts("");
}
}
return 0;
}
UNSOLVED_D - Vin Diagrams
ICPC 7982 - Vin Diagrams
E - 最短路径·三:SPFA算法
HihoCoder - 1093
SPFA
SPFA是运用队列,把所有的点遍历到没有能更新的,点可以重复入队
关于SPFA,它死了
仅用于判断负权环,没有负权边的最短路使用dijkstra
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N = 100005;
int n, m, s, t, dist[N]; //到起点的最短距离
bool in[N];
vector<pair<int, int>> v[N]; //编号,距离
int SPFA()
{
queue<int> Q;
for (int i = 1; i <= n; i++)
dist[i] = __INT32_MAX__, in[i] = false;
dist[s] = 0;
Q.push(s);
in[s] = true;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
in[u] = false;
for (int i = v[u].size() - 1; i >= 0; i--)
{
int j = v[u][i].first;
if (dist[j] > dist[u] + v[u][i].second)
{
dist[j] = dist[u] + v[u][i].second;
if (!in[j])
{
Q.push(j);
in[j] = true;
}
}
}
}
return dist[t];
}
int main()
{
cin >> n >> m >> s >> t;
int x, y, c;
for (int i = 1; i <= m; i++)
{
cin >> x >> y >> c;
v[x].push_back(make_pair(y, c));
v[y].push_back(make_pair(x, c));
}
cout << SPFA();
}
dijkstra
dijkstra是每次找出离源点最近的点确定位置,不可重复确定
Dijkstra使用优先队列,虽然同一个点可以多次入队,但是保证了一个点真正pop出来刷新其他点的时候只有一次.
https://blog.csdn.net/Newbie006/article/details/79674791
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int n, m, s, t;
using p = pair<int, int>;
vector<p> edge[MAXN]; // 距离 , 序号
int dis[MAXN];
int dijkstra()
{
priority_queue<p, vector<p>, greater<p>> que; // 距离,序号;
fill(dis, dis + 1 + n, __INT32_MAX__);
dis[s] = 0;
que.push(make_pair(0, s));
while (!que.empty())
{
int d = que.top().first, num = que.top().second;
que.pop();
if (dis[num] < d)
continue;
for (int i = 0; i < edge[num].size(); i++)
{
p temp = edge[num][i];
if (dis[temp.second] > dis[num] + temp.first)
{
dis[temp.second] = dis[num] + temp.first;
que.push(make_pair(dis[temp.second], temp.second));
}
}
}
return dis[t];
}
int main(void)
{
cin >> n >> m >> s >> t;
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
edge[a].push_back(make_pair(c, b));
edge[b].push_back(make_pair(c, a));
}
cout << dijkstra();
return 0;
}
F - Flight
HDU - 3499
题意:有一个n个结点,m条边的有向图,可以对一条边进行边权减半的操作。问起点到终点的最短路
分层图最短路dijkstra
仅对字符串进行hash,不需要按序输出,unordered_map更优
dis[]
数组不用ll,会wa
#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define mp(a, b) make_pair(a, b)
using namespace std;
using ll = long long;
ll dis[200002]; //保存距离的数组要用ll,否则会wa
// map<string, int> mapp; 使用unordered_map , 耗时缩短一半
unordered_map<string, int> mapp;
using p = pair<int, int>; //这里不能用ll,否则会mle
vector<p> edge[200002];
void dijkstra(int start) //分层最短路的dijkstra()就是模板,没有变化
{
priority_queue<p, vector<p>, greater<p>> que;
que.push(mp(0, start));
dis[start] = 0;
while (!que.empty())
{
p now = que.top();
que.pop();
if (now.first > dis[now.second])
continue;
for (int i = 0; i < edge[now.second].size(); i++)
{
p next = edge[now.second][i];
if (dis[next.second] > dis[now.second] + next.first)
{
dis[next.second] = dis[now.second] + next.first;
que.push(mp(dis[next.second], next.second));
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, m;
while (cin >> n >> m)
{
int id = 1;
mapp.clear();
for (int i = 0; i < 2 * n + 2; i++)
{
edge[i].clear();
dis[i] = __LONG_LONG_MAX__;
}
for (int i = 0; i < m; i++)
{
string a, b;
int val;
cin >> a >> b >> val;
if (!mapp[a])
mapp[a] = id++;
if (!mapp[b])
mapp[b] = id++;
edge[mapp[a]].push_back(mp(val, mapp[b])); //第一层
edge[mapp[a] + n].push_back(mp(val, mapp[b] + n)); //第二层
edge[mapp[a]].push_back(mp(val / 2, mapp[b] + n)); //第一层到第二层,就是使用打折机票
}
string start, end;
cin >> start >> end;
if (m == 0)
{
cout << -1 << endl;
continue;
}
dijkstra(mapp[start]);
ll ans = min(dis[mapp[end]], dis[mapp[end] + n]);
if (ans == __LONG_LONG_MAX__)
ans = -1;
cout << ans << endl;
}
}
G - Free DIY Tour
HDU-1224
最长路
基于dijkstra的最长路
#include <iostream>
#include <stack>
#include <queue>
#define mp(a, b) make_pair(a, b)
using namespace std;
using p = pair<int, int>;
vector<pair<int, int>> edge[110];
int dis[110];
int path[110];
void dijkstra(int tar)
{
priority_queue<pair<int, int>> que;
que.push(mp(0, 1));
dis[1] = 0;
while (!que.empty())
{
p now = que.top();
que.pop();
if (now.first < dis[now.second])
continue;
for (int i = 0; i < edge[now.second].size(); i++)
{
p t = edge[now.second][i];
if (dis[t.second] < dis[now.second] + t.first)
{
dis[t.second] = dis[now.second] + t.first;
que.push(mp(dis[t.second], t.second));
path[t.second] = now.second;
}
}
}
cout << "points : " << dis[tar] << endl;
cout << "circuit : ";
stack<int> q;
q.push(1);
tar = path[tar];
while (tar != -1)
{
q.push(tar);
tar = path[tar];
}
q.pop();
cout << 1;
while (!q.empty())
{
cout << "->" << q.top();
q.pop();
}
cout << endl;
}
int main(void)
{
int t;
cin >> t;
for (int j = 0; j < t; j++)
{
int n;
cin >> n;
vector<int> val;
val.resize(n + 1);
fill(path, path + 110, -1);
fill(dis, dis + 110, -1);
for (int i = 0; i < n; i++)
{
edge[i].clear();
cin >> val[i];
}
val[n] = 0;
int k;
cin >> k;
for (int i = 0; i < k; i++)
{
int a, b;
cin >> a >> b;
edge[a].push_back(mp(val[b - 1], b));
}
if (j != 0)
cout << endl;
cout << "CASE " << j + 1 << "#" << endl;
dijkstra(n + 1);
}
return 0;
}
基于SPFA的最长路
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <math.h>
#include <memory>
#include <queue>
using namespace std;
typedef long long LL;
#define max_v 120
int n, m;
int G[max_v][max_v];
int a[max_v];
int dis[max_v]; //保存價值
int way[max_v]; //保存路
void spfa(int s, int tn)
{
for (int i = 1; i <= tn; i++)
{
dis[i] = 0;
way[i] = 0;
}
queue<int> q;
q.push(s);
int p;
while (!q.empty())
{
p = q.front();
q.pop();
for (int i = 1; i <= tn; i++)
{
if (G[p][i] != 0)
{
if (dis[p] + a[i] > dis[i])
{
dis[i] = dis[p] + a[i];
way[i] = p;
q.push(i);
}
}
}
}
}
void pri(int tn) //路徑打印
{
int a[300];
int c = 1;
int i = tn;
while (way[i])
{
a[c++] = way[i];
i = way[i];
}
for (int i = c - 1; i >= 1; i--)
{
printf("%d->", a[i]);
}
printf("1
");
}
int main()
{
int t;
scanf("%d", &t);
int k = 1;
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
a[n + 1] = 0;
scanf("%d", &m);
memset(G, 0, sizeof(G));
for (int i = 1; i <= m; i++)
{
int x, y;
scanf("%d %d", &x, &y);
G[x][y] = 1;
}
spfa(1, n + 1);
if (k != 1)
printf("
");
printf("CASE %d#
", k++);
printf("points : %d
", dis[n + 1]);
printf("circuit : ");
pri(n + 1);
}
return 0;
}
H - 棋盘问题
POJ - 1321
#include <iostream>
using namespace std;
int n, k;
bool board[10][10];
bool vis[10];
int ans, cnt;
void dfs(int cur)
{
if (cnt == k)
{
ans++;
return;
}
if (cur > n - 1) // 0 - n-1
{
return;
}
for (int i = 0; i < n; i++)
{
if (vis[i] == false and board[cur][i])
{
vis[i] = true;
cnt++;
dfs(cur + 1);
vis[i] = false;
cnt--;
}
}
dfs(cur + 1);
}
int main()
{
while (cin >> n >> k and n != -1 and k != -1)
{
cnt = ans = 0;
fill(vis, vis + 10, false);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
char t;
cin >> t;
board[i][j] = (t == '#' ? true : false);
}
}
dfs(0);
cout << ans << endl;
}
}
I - Dungeon Master
POJ - 2251
三维迷宫问题,简单的BFS,搜索六个方向.
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
struct node
{
int x, y, z, m;
node(int x, int y, int z, int m) : x(x), y(y), z(z), m(m) {}
};
int l, r, c;
char board[35][35][35];
bool vis[35][35][35];
int sx, sy, sz, ex, ey, ez;
//向北、向南、向东、向西移动,向上或向下移动一个单位
int dir[6][3] = {{1, 0, 0},
{-1, 0, 0},
{0, 1, 0},
{0, -1, 0},
{0, 0, 1},
{0, 0, -1}};
int bfs()
{
queue<node> que;
que.push(node(sx, sy, sz, 0));
vis[sx][sy][sz] = true;
while (!que.empty())
{
node top = que.front();
que.pop();
if (top.x == ex and top.y == ey and top.z == ez)
{
return top.m;
}
for (int i = 0; i < 6; i++)
{
int x = dir[i][0] + top.x;
int y = dir[i][1] + top.y;
int z = dir[i][2] + top.z;
if (vis[x][y][z] == false and x >= 0 and x < l and y >= 0 and y < r and z >= 0 and z < c and board[x][y][z] != '#')
{
vis[x][y][z] = true;
que.push(node(x, y, z, top.m + 1));
}
}
}
return -1;
}
int main()
{
while (cin >> l >> r >> c and l != 0 and r != 0 and c != 0)
{
// memset(vis, sizeof(vis), 0); //脑瘫错误,找了好久
memset(vis, 0, sizeof(vis));
for (int i = 0; i < l; i++)
{
for (int j = 0; j < r; j++)
{
for (int k = 0; k < c; k++)
{
cin >> board[i][j][k];
if (board[i][j][k] == 'S')
{
sx = i, sy = j, sz = k;
}
if (board[i][j][k] == 'E')
{
ex = i, ey = j, ez = k;
}
}
}
}
int ans = bfs();
if (ans == -1)
cout << "Trapped!" << endl;
else
cout << "Escaped in " << ans << " minute(s)." << endl;
}
return 0;
}
我吐了,memset用错了,找了好久.
学习下std::fill()
的用法,使用它
关于memset()的限制
因为memset赋值时按照字节填充,所以更适合给char类型的数组赋值(一维/二维),因为在c/c++中char占用1一个字节(8位),而int占用2个字节,如果要使用memset给int赋值只适用于0,-1,但还有一种巧妙的方法,如果要将一个数组(一维/二维)全部赋值一个很大的值也可以通过将这个最大值M设置为0x3f3f3f3f(这是一个很巧妙的数字具体有兴趣的童鞋可以去查一下原因哦)
memset也可对浮点数组赋 0 值 ( 使用IEEE-754标准 ), 一些讨论见 Stackoverflow
关于std::fill()
定义于头文件
int b[10];
fill(b, b + 10, -1);
int c[10][10];
fill(c[0], c[0] + 10 * 10, -1);
int a[20][20][20];
fill(a[0][0], a[0][0] + 20 * 20 * 20, -1);
在o2
以上的优化时,std::fill()
和memset
的性能表现相近,简单测试可见StackOverflow
J - Flip Game UNSOLVED_
POJ - 1753
K - 非常可乐
HDU - 1495
bfs
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int s, n, m; //S==N+M
bool vis[101][101][101];
int bottle[3];
struct node
{
int cap[3], step;
node(int a, int b, int c, int d)
{
cap[0] = a;
cap[1] = b;
cap[2] = c;
step = d;
}
};
bool judge(node &t)
{
if ((t.cap[0] == 0 and t.cap[1] == t.cap[2]) or (t.cap[1] == 0 and t.cap[0] == t.cap[2]) or (t.cap[2] == 0 and t.cap[0] == t.cap[1]))
return true;
return false;
}
int bfs()
{
memset(vis, 0, sizeof(vis));
queue<node> que;
que.push(node(s, 0, 0, 0));
vis[s][0][0] = true;
while (!que.empty())
{
node top = que.front();
que.pop();
if (judge(top))
return top.step;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i != j)
{
if (top.cap[i] == 0)
continue;
else
{
node t = top;
if (t.cap[i] + t.cap[j] < bottle[j])
{
t.cap[j] += t.cap[i];
t.cap[i] = 0;
}
else
{
t.cap[i] -= (bottle[j] - t.cap[j]);
t.cap[j] = bottle[j];
}
if (vis[t.cap[0]][t.cap[1]][t.cap[2]] == false)
{
vis[t.cap[0]][t.cap[1]][t.cap[2]] = true;
que.push(node(t.cap[0], t.cap[1], t.cap[2], t.step + 1));
}
}
}
}
}
}
return -1;
}
int main()
{
while (cin >> s >> n >> m and s != 0 and n != 0 and m != 0)
{
if (s % 2 == 1)
{
cout << "NO" << endl;
continue;
}
bottle[0] = s;
bottle[1] = n;
bottle[2] = m;
int ans = bfs();
if (ans == -1)
cout << "NO" << endl;
else
cout << ans << endl;
}
return 0;
}
L - Prime Path UNSOLVED_
POJ - 3126
M - Find a way
HDU - 2612
两次简单的bfs
因为continue
wa 好几次
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;
char board[202][202];
bool vis[202][202];
int n, m;
int start[2][2];
struct node
{
int x, y, step;
node(int x, int y, int s) : x(x), y(y), step(s) {}
};
vector<node> ans[2];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
void bfs(int x, int y, int who)
{
memset(vis, 0, sizeof(vis));
queue<node> que;
que.push(node(x, y, 0));
vis[x][y] = true;
while (!que.empty())
{
node now = que.front();
que.pop();
if (board[now.x][now.y] == '@')
{
ans[who].push_back(node(now.x, now.y, now.step));
// continue; 这里wa好几次
}
for (int i = 0; i < 4; i++)
{
int tx = now.x + dir[i][0];
int ty = now.y + dir[i][1];
if (tx >= 0 and tx < n and ty >= 0 and ty < m and board[tx][ty] != '#' and !vis[tx][ty])
{
vis[tx][ty] = true;
que.push(node(tx, ty, now.step + 1));
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
while (cin >> n >> m)
{
ans[0].clear();
ans[1].clear();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> board[i][j];
if (board[i][j] == 'Y')
{
start[0][0] = i;
start[0][1] = j;
}
if (board[i][j] == 'M')
{
start[1][0] = i;
start[1][1] = j;
}
}
}
bfs(start[0][0], start[0][1], 0);
bfs(start[1][0], start[1][1], 1);
int res = __INT32_MAX__;
for (int i = 0; i < ans[0].size(); i++)
{
for (int j = 0; j < ans[1].size(); j++)
{
if (ans[0][i].x == ans[1][j].x and ans[0][i].y == ans[1][j].y)
{
res = min(res, ans[0][i].step + ans[1][j].step);
}
}
}
cout << res * 11 << endl;
}
return 0;
}
N - Shuffle'm Up
POJ - 3087
直接模拟
#include <iostream>
#include <string>
// #include <unordered_set> POJ 貌似不支持C++11及以上标准
#include <set>
using namespace std;
int main()
{
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
string tar;
int c;
set<string> vis;
vis.clear();
cin >> c;
string a, b;
cin >> a >> b;
cin >> tar;
string t;
int count(0);
cout << i + 1 << ' ';
while (true)
{
t.clear();
for (int i = 0; i < c; i++)
{
t.push_back(b[i]);
t.push_back(a[i]);
}
count++;
if (vis.find(t) == vis.end())
{
vis.insert(t);
}
else
{
cout << -1 << endl;
break;
}
if (t == tar)
{
cout << count << endl;
break;
}
a.clear();
b.clear();
for (int i = 0; i < c; i++)
{
a.push_back(t[i]);
}
for (int i = c; i < 2 * c; i++)
{
b.push_back(t[i]);
}
}
}
return 0;
}
O - Pots
POJ - 3414
#include <iostream>
#include <string>
#include <queue>
using namespace std;
int a, b, c;
// FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
// DROP(i) empty the pot i to the drain;
// POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
string path[] = {
"FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
struct node
{
int a, b;
vector<int> id;
};
bool vis[101][101] = {false};
void bfs()
{
queue<node> que;
node t;
t.a = 0;
t.b = 0;
que.push(t);
vis[a][b] = true;
while (!que.empty())
{
node now = que.front();
que.pop();
if (now.a == c or now.b == c)
{
cout << now.id.size() << endl;
for (int i = 0; i < now.id.size(); i++)
{
cout << path[now.id[i]] << endl;
}
return;
}
t = now;
if (t.a != a)
{
t.a = a;
t.b = now.b;
t.id = now.id;
if (!vis[t.a][t.b])
{
vis[t.a][t.b] = true;
t.id.push_back(0);
que.push(t);
}
}
t = now;
if (t.b != b)
{
t.a = now.a;
t.b = b;
t.id = now.id;
if (!vis[t.a][t.b])
{
vis[t.a][t.b] = true;
t.id.push_back(1);
que.push(t);
}
}
// "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
// DROP(a)
t = now;
if (t.a)
{
t.a = 0;
t.b = now.b;
if (!vis[t.a][t.b])
{
vis[t.a][t.b] = true;
t.id.push_back(2);
que.push(t);
}
}
// DROP(b)
t = now;
if (t.b)
{
t.b = 0;
if (!vis[t.a][t.b])
{
vis[t.a][t.b] = true;
t.id.push_back(3);
que.push(t);
}
}
// POUR(a,b)
t = now;
if (t.a && (t.b < b))
{
if (t.a > (b - t.b))
{
t.a = now.a - (b - now.b);
t.b = b;
}
else
{
t.a = 0;
t.b = now.b + now.a;
}
if (!vis[t.a][t.b])
{
vis[t.a][t.b] = true;
t.id.push_back(4);
que.push(t);
}
}
// POUR(b,a)
t = now;
if (t.b && (t.a < a))
{
if (t.b > (a - t.a))
{
t.a = a;
t.b = now.b - (a - now.a);
}
else
{
t.a = now.a + now.b;
t.b = 0;
}
if (!vis[t.a][t.b])
{
vis[t.a][t.b] = true;
t.id.push_back(5);
que.push(t);
}
}
}
cout << "impossible" << endl;
}
int main()
{
cin >> a >> b >> c;
bfs();
return 0;
}
P - Fire!
UVA - 11624
https://blog.csdn.net/PK__PK/article/details/79116110
#include <cstdio>
#include <iostream>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 1010;
char map[maxn][maxn]; // 地圖
int book[maxn][maxn]; // 標記陣列,記錄這點火或者人是否走過
struct node
{
int x; //座標x
int y; // 座標y
int step; // 人的步數
int kind; // 用來區分是人還是火,1是人,0是火
};
queue<node> q;
int n, m, ans; // n,m表示長寬。ans表示火的個數
node ren; //記錄人的起始位置
node fire[maxn]; // 記錄火的起始位置
int mov[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; // 移動陣列
void bfs()
{
node now, next;
for (int i = 0; i < ans; i++)
{ // 先把火入佇列
q.push(fire[i]);
}
q.push(ren); // 再把人放入佇列
// cout<<ren.step<<endl;
while (!q.empty())
{
now = q.front();
q.pop();
if (now.kind == 1 && (now.x == 0 || now.y == 0 || now.x == n - 1 || now.y == m - 1))
{ // 當是人到達邊緣時
cout << now.step + 1 << endl;
return;
}
for (int i = 0; i < 4; i++)
{ // 對火對人進行移動
next.x = now.x + mov[i][0];
next.y = now.y + mov[i][1];
if (next.x < 0 || next.x >= n || next.y < 0 || next.y >= m || book[next.x][next.y] == 1 || map[next.x][next.y] == '#') //判斷是否可走和越界
continue;
next.kind = now.kind; // 記錄種類
book[next.x][next.y] = 1; // 標記已走
// printf("%d %d %d
",next.x,next.y,next.step);
if (now.kind) // 若為人 順帶記錄步數
next.step = now.step + 1;
q.push(next); //入佇列
}
}
cout << "IMPOSSIBLE" << endl;
}
int main()
{
int z;
cin >> z;
while (z--)
{
while (!q.empty())
q.pop(); // 清空很重要
memset(map, 0, sizeof(map));
memset(book, 0, sizeof(book));
ans = 0;
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> map[i]; // 輸入地圖資訊
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (map[i][j] == 'J')
{ // 查詢人的起始位置
ren.x = i;
ren.y = j;
ren.step = 0;
ren.kind = 1;
}
if (map[i][j] == 'F')
{ // 查詢所有火的起始位置
fire[ans].x = i;
fire[ans].y = j;
fire[ans].kind = 0;
fire[ans].step = 0;
ans++;
book[i][j] = 1;
}
}
}
bfs();
}
return 0;
}
/*
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F
*/