bfs
ABC 235 D - Multiply and Rotate
题目链接
https://atcoder.jp/contests/abc235/tasks/abc235_d
解析
- 注意bfs是一种工具,不局限于图论,本质是搜索
- 本题相当于给出了两种扩展队列的规则,按照规则进行扩展求最短路即可
- 感觉to_string()方法用于求数字的位数很nice
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e7 + 10;
bool st[N];
int a, n;
int dist[N];
int qmi(int a, int k)
{
int res = 1;
while(k)
{
if(k & 1) res = (ll) res * a;
k >>= 1;
a = (ll)a * a;
}
return res;
}
int check1(int x){
if(x < 10 || x % 10 == 0) return x;
string s = to_string(x);
int len = s.size();
return x % 10 * qmi(10, len - 1) + x / 10;
}
int check2(int x){
return a * x;
}
int main()
{
scanf("%d%d", &a, &n);
memset(dist, 0x3f, sizeof dist);
string nn = to_string(n);
int LEN = nn.size();
queue<int> q;
q.push(1);
st[1] = true; dist[1] = 0;
while(q.size()){
auto t = q.front();
q.pop();
int newt = check1(t);
string tt = to_string(newt);
int lent = tt.size();
if(lent <= LEN && !st[newt]){
q.push(newt);
st[newt] = true;
dist[newt] = dist[t] + 1;
}
newt = check2(t);
tt = to_string(newt);
lent = tt.size();
if(lent <= LEN && !st[newt]){
q.push(newt);
st[newt] = true;
dist[newt] = dist[t] + 1;
}
}
if(dist[n] == 0x3f3f3f3f) puts("-1");
else printf("%d\n", dist[n]);
return 0;
}
1855. 愤怒的奶牛
题目链接
https://www.acwing.com/problem/content/1857/
解析
一个一维的bfs+暴力,暴力枚举每一个最开始击中的点,然后通过bfs把所有符合要求的点加进队列,然后更新下一轮的点。需要注意的有两点:
-
统计会爆炸的点的个数:将每个会爆炸的点加进队列,在每个点出队列的时候记一个cnt就行;不要只加入每轮引爆最左边和最右边的点,这样可能是不全面的。
-
学习怎么一轮一轮地改变爆炸范围
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
const int N = 110;
int cnt;
int start, n;
queue<int> q;
int a[N];
bool st[N];
map<int, int> mp;
void bfs(int x)
{
cnt = 0;
memset(st, 0, sizeof st);
mp[x] = 1;
q.push(x);
st[x] = true;
int right, left;
while(q.size())
{
int s = q.front(); q.pop();
cnt ++;
left = s - 1, right = s + 1;
while(left >= 1 && a[s] - a[left] <= mp[s]) {
if(st[left]) left --;
else{
q.push(left);
st[left] = true;
mp[left] = mp[s] + 1;
left --;
}
}
while(right <= n && a[right] - a[s] <= mp[s]) {
if(st[right]) right ++;
else{
q.push(right);
st[right] = true;
mp[right] = mp[s] + 1;
right ++;
}
}
}
return;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
int ans = 0;
for(int i = 1; i <= n; i ++){
bfs(i);
ans = max(ans, cnt);
}
printf("%d\n", ans);
return 0;
}
844. 走迷宫
题目链接
https://www.acwing.com/problem/content/846/
解析
bfs模板题
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int a[N][N], d[N][N];
bool st[N][N];
int n, m;
queue<PII> q;
void bfs(int xx, int yy)
{
q.push({xx, yy});
st[xx][yy] = true;
d[1][1] = 0;
while(q.size()){
auto t = q.front(); q.pop();
int tx = t.first, ty = t.second;
for(int i = 0; i < 4; i ++){
int x = tx + dx[i], y = ty + dy[i];
if(x < 1 || x > n || y < 1 || y > m) continue;
if(a[x][y] == 1) continue;
if(st[x][y]) continue;
if(d[x][y] > d[tx][ty] + 1){
q.push({x, y});
st[x][y] = true;
d[x][y] = d[tx][ty] + 1;
}
}
}
return;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
scanf("%d", &a[i][j]);
}
}
memset(d, 0x3f, sizeof d);
bfs(1, 1);
printf("%d\n", d[n][m]);
return 0;
}
845. 八数码
题目链接
https://www.acwing.com/problem/content/847/
解析
感觉像是一个状态压缩的bfs,需要注意的技巧有以下几点:
- 字符串和3x3方格坐标的转化
- <unordered_map> 有 .count()方法,可以发挥st数组的作用
- 总是写错数组的边界,关于数组越界的判断要特别注意
- swap很好用,string里交换字符也可以用swap
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
const int N = 15;
string str = "12345678x";
string a;
queue<string> q;
unordered_map<string, int> d;
int find(string s, char x){
for(int i = 0; i < 9; i ++)
if(s[i] == x) return i;
return -1;
}
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int bfs(string a)
{
q.push(a);
d[a] = 0;
while(q.size())
{
auto t = q.front(); q.pop();
int distance = d[t];
if(t == str) return d[t];
int pos = find(t, 'x');
int tx = pos / 3, ty = pos % 3;
for(int i = 0; i < 4; i ++){
int x = tx + dx[i], y = ty + dy[i];
if(x < 0 || x >= 3 || y < 0 || y >= 3) continue;
swap(t[pos], t[3 * x + y]);
if(!d.count(t)){
q.push(t);
d[t] = distance + 1;
}
swap(t[pos], t[3 * x + y]);
}
}
return -1;
}
int main()
{
for(int i = 0; i < 9; i ++){
char x;
cin >> x;
a += x;
};
printf("%d\n", bfs(a));
return 0;
}
1471. 牛奶工厂
题目链接
https://www.acwing.com/problem/content/1473/
解析
暴力。和拓扑排序的板子有点像。
Ac代码
点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 110;
int n;
int h[N], e[N], ne[N], idx;
bool st[N];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool bfs(int x)
{
int cnt = 0;
memset(st, 0, sizeof st);
queue<int> q;
q.push(x);
st[x] = true;
while(q.size()){
auto t = q.front(); q.pop();
cnt ++;
for(int i = h[t]; i != -1; i = ne[i]){
int j = e[i];
if(!st[j]){
q.push(j);
st[j] = true;
}
}
}
if(cnt == n) return true;
return false;
}
int main()
{
scanf("%d", &n);
memset(h, -1, sizeof h);
for(int i = 1; i < n; i ++){
int a, b;
scanf("%d%d", &a, &b);
add(b, a);
}
for(int i = 1; i <= n; i ++){
if(bfs(i)){
printf("%d\n", i);
return 0;
}
}
printf("-1\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架