当前位置: 首页 > wzjs >正文

最低多少钱可以注册公司漯河搜狗关键词优化排名软件

最低多少钱可以注册公司,漯河搜狗关键词优化排名软件,东莞东城区疫情最新消息,武汉群体事件最新宽度优先搜索的过程中,每次都会从当前点向外扩展⼀层,所以会具有⼀个最短路的特性。因此,宽搜不仅能搜到所有的状态,⽽且还能找出起始状态距离某个状态的最⼩步数。 但是,前提条件是每次扩展的代价都是 1 ,…

宽度优先搜索的过程中,每次都会从当前点向外扩展⼀层,所以会具有⼀个最短路的特性。因此,宽搜不仅能搜到所有的状态,⽽且还能找出起始状态距离某个状态的最⼩步数

但是,前提条件是每次扩展的代价都是 1 ,或者都是相同的数。宽搜常常被⽤于解决边权为 1 的最短路问题。

一、BFS

1. ⻢的遍历

题⽬来源:洛⾕

题⽬链接:P1443 马的遍历 - 洛谷

难度系数:★★

(1)题目描述

(2)算法原理

题⽬要求到达某个点最少要⾛⼏步,因此可以⽤ bfs 解决。因为当权值为 1 时,bfs 每次都是扩展
距离起点等距离的⼀层,天然具有最短性。
那就从起点开始,⼀层⼀层的往外搜,⽤⼀个 dist 数组记录最短距离。 

(3)参考代码

#include <iostream>
#include <queue>
#include <cstring>using namespace std;typedef pair<int, int> PII;const int N = 410;int n, m, x, y;
int dist[N][N];int dx[] = {1, 2, 2, 1, -1, -2, -2, -1};
int dy[] = {2, 1, -1, -2, -2, -1, 1, 2};void bfs()
{memset(dist, -1, sizeof dist);queue<PII> q;q.push({x, y});dist[x][y] = 0;while(q.size()){auto t = q.front(); q.pop();int i = t.first, j = t.second;for(int k = 0; k < 8; k++){int x = i + dx[k], y = j + dy[k];if(x < 1 || x > n || y < 1 || y > m) continue;if(dist[x][y] != -1) continue;dist[x][y] = dist[i][j] + 1; // 更细结果q.push({x, y});}}
}int main()
{cin >> n >> m >> x >> y;bfs();for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cout << dist[i][j] << " ";}cout << endl;}return 0;
}

2. kotori和迷宫

题⽬来源:⽜客⽹

题⽬链接:kotori和迷宫

难度系数:★★

(1)题目描述

(2)算法原理

经典 bfs 问题。

从迷宫的起点位置逐层开始搜索,每搜到⼀个点就标记⼀下最短距离。当把整个迷宫全部搜索完毕之 后,扫描整个标记数组,求出出⼝的数量以及最短的距离。

注意:走到 "e" 之后就不能继续遍历了

(3)参考代码

#include <iostream>
#include <queue>
#include <cstring>using namespace std;typedef pair<int, int> PII;const int N = 35;int n, m, x, y;
char a[N][N];
int dist[N][N];int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};void bfs()
{memset(dist, -1, sizeof dist);queue<PII> q;q.push({x, y});dist[x][y] = 0;while(q.size()){auto t = q.front(); q.pop();int i = t.first, j = t.second;for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];if(x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] != '*' && dist[x][y] == -1){dist[x][y] = dist[i][j] + 1;if(a[x][y] == 'e') {continue;}q.push({x, y});}}}
}int main()
{cin >> n >> m;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cin >> a[i][j];if(a[i][j] == 'k'){x = i; y = j;}}}bfs();// 统计结果int cnt = 0, ret = 1e9;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){if(a[i][j] == 'e' && dist[i][j] != -1){cnt++;ret = min(ret, dist[i][j]);}}}if(cnt == 0) cout << -1 << endl;else cout << cnt << " " << ret << endl;return 0;
}

3. CatchThatCow

题⽬来源:洛⾕

题⽬链接:P1588 [USACO07OPEN] Catch That Cow S - 洛谷

难度系数:★★

(1)题目描述 

(2)算法原理

暴⼒举出所有的⾏⾛路径,因为是求少步数以⽤ bfs 解决

  • 从起点位搜索,每次向外扩展三⾏⾛⽅式;
  • 第⼀次到⽜的位置时就是短距离。

如果做任何理,时间和都会。因为我们会搜索多⽆效的位们要加上剪

  • 当 −1 减到负数的时候,剪掉;

        因为如果⾛到负数还是需要回头⾛到正数⼀定不是最优

  • 当 +1 操作越过 y 的时候,剪掉; 

        如果 +1 之后⼤于 y ,说⾝就 位置或者 的右侧,你右⾛还是需再向左⾛去。⼀定不是最优掉。

  • y 是偶数,并且当 ×2 操作之后⼤于 y 的时候,剪掉,

因为不如先减到  y ⼀半后再乘;设当前数是 x ,那

  • 先乘后减,总的步数 t1 = 2x y + 1
  • 先减后乘,总的步数 t2 = x y/2 + 1
  • t1 t2 = 2x y + 1 (x y/2 + 1) = x y/2 > 0
  • 先乘后减不如先减后乘

y 是奇数候,那 y + 1 就是,根据 3 得,×2 超过y + 1

(3)参考代码

#include <iostream>
#include <queue>
#include <cstring>using namespace std;const int N = 1e5 + 10;int n = 1e5;
int x, y;
int dist[N];void bfs()
{queue<int> q;q.push(x);dist[x] = 0;while(q.size()){auto t = q.front(); q.pop();int a = t + 1, b = t - 1, c = t * 2;if(a <= n && dist[a] == -1){dist[a] = dist[t] + 1;q.push(a);}if(b > 0 && dist[b] == -1){dist[b] = dist[t] + 1;q.push(b); }if(c <= n && dist[c] == -1){dist[c] = dist[t] + 1;q.push(c);}// 剪枝if(a == y || b == y || c == y) return;}
}int main()
{int T; cin >> T;while(T--){// 注意清空数据memset(dist, -1, sizeof dist);cin >> x >> y;bfs();cout << dist[y] << endl;}return 0;
}

4. ⼋数码难题

题⽬来源:洛⾕

题⽬链接:P1379 八数码难题 - 洛谷

难度系数:★★★

(1)题目描述

(2)算法原理

经过之前么多题垫,这道题还是容易的。因短步数,因此可以⽤bfs 解决。

  • 从起始状态开每次扩展上下左右交态;
  • 在搜索的第⼀次遇到终状就返回最短步数

理虽然容易,但是实⽐较⿇烦,们要想下⾯⼏情:

  • 如何记录⼀个3 × 3 的棋盘?

⽤字符串从上从左右将盘内次存到⼀个字符串⾥,来标记棋态。

  • 如何记录最短路?

⽤ unordered_map < string, int > 来标记最短距离;

  • 如何通过⼀个字符串找到交换之后的字符串?

策略⼀先把字符串还原成⼆维矩阵,然后交 0 成字符串。与四数字,最后再把交之后的棋盘还原成字符串。

虽然可⾏,但是太过于⿇烦。其实可通过,快出⼆维坐标与⼀维下相互转前后的值。如下图:

这个技巧特别常⽤以推⼴到 n × 的矩阵坐标 (x, y) 映射成⼀个数 pos 起到空间果。后续题中我遇到

接在字符串中找出交前后标,字符串对应能得到交之后态。

(3)参考代码

#include <iostream>
#include <unordered_map>
#include <queue>using namespace std;string s;
string aim = "123804765";
unordered_map<string, int> dist;int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};void bfs()
{queue<string> q;q.push(s);dist[s] = 0;while(q.size()){string t = q.front(); q.pop();int pos = 0;while(t[pos] != '0') pos++;int x = pos / 3, y = pos % 3; // 计算二维矩阵中对应的位置for(int i = 0; i < 4; i++){int a = x + dx[i], b = y + dy[i];if(a >= 0 && a <= 2 && b >= 0 && b <= 2){string next = t;// (x, y) 与 (a, b) 做交换int p = 3 * a + b;swap(next[p], next[pos]);if(dist.count(next)) continue;dist[next] = dist[t] + 1;q.push(next);if(next == aim) return; // 剪枝}}}
}int main()
{cin >> s;bfs();cout << dist[aim] << endl;return 0;
}

二、多源BFS

  • 单源最短路问题 vs 多源最短路问题
  1. 问题中只存⼀个起这时的最短路问题就是单源最短路问题
  2. 问题中存多个起⽽不是单⼀起这时的最短路问题就是多源最短路问题
  • 多源 BFS

        多源最短路问题权都  时,此时就可⽤多BFS 解决

  • 解决⽅式

        把这些源点汇聚在⼀起,当成⼀个"超级源点"。然后从这个"超级源点"开始,处理最短路问题

码上时

  1. 初始化候,把所有的源点都加⼊到队列⾥⾯
  2. 后正常执⾏ bfs 逻辑即可

        也就是初始化的候,⽐普通 bfs 多加⼊⼏个起点。

1. 矩阵距离

题⽬来源:⽜客⽹

题⽬链接:矩阵距离

难度系数:★★

(1)题目描述

(2)算法原理 

正难则反

  • 如果针对某⼀个点,直接去找最近的 1 ,我们需要对所有的 0 都来⼀次 bfs,这个时间复杂度是 接受不了的。
  • 但是我们如果反着来想,从 1 开始向外扩展,每遍历到⼀个 0 就更新⼀下最短距离。这样仅需⼀ 次 bfs,就可以把所有点距离 1 的最短距离更新出来。

        由于 1 的数量很多,因此可以把所有的 1 看成⼀个超级源点,从这个超级源点开始⼀层⼀层的向外 扩展。实现起来也很简单,就是在初始化阶段把所有 1 的坐标加⼊到队列中,然后正常 bfs  。

(3)参考代码

#include <iostream>
#include <queue>
#include <cstring>using namespace std;typedef pair<int, int> PII;const int N = 1010;int n, m;
char a[N][N];
int dist[N][N];int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};void bfs()
{memset(dist, -1, sizeof dist);queue<PII> q;// 1. 所有的起点加入到队列里面for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)if(a[i][j] == '1'){q.push({i, j});dist[i][j] = 0;}// 2. 正常的 bfswhile(q.size()){auto t = q.front(); q.pop();int x = t.first, y = t.second;for(int i = 0; i < 4; i++){int a = x + dx[i], b = y + dy[i];if(a >= 1 && a <= n && b >= 1 && b <= m && dist[a][b] == -1){dist[a][b] = dist[x][y] + 1;q.push({a, b});}}}
}int main()
{cin >> n >> m;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)cin >> a[i][j];bfs();for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cout << dist[i][j] << " ";}cout << endl;}return 0;
}

2. 刺杀⼤使

题⽬来源:洛⾕

题⽬链接:P1902 刺杀大使 - 洛谷

难度系数:★★★

(1)题目描述

(2)算法原理

        直接找答是不的,因是太多了都枚举出时间上吃不消。但题⽬值最⼩化尝试⽤⼆分来优化枚举

设最终结是 x ,会⼀个

  • 规定搜索的最⼤于等于  x ⼀定可从第⼀⾏⾛到后⼀⾏
  • 当规定搜索的最⼩于  x ⼀定不⾛到后⼀⾏

        因此⼆分终结果,通过 bfs 或者 dfs 判断是否⾛到后⼀⾏

        如果⽤ dfs  ,那就从第⼀⾏每⼀列都搜索⼀遍⽤ bfs 看成多源 bfs 问题直接把所有的源点加⼊队列中,然后正常搜索即可

(3)参考代码

#include <iostream>
#include <queue>
#include <cstring>using namespace std;typedef pair<int, int> PII;const int N = 1010;int n, m;
int p[N][N];
bool st[N][N]; // 在宽搜的过程中,不走重复路int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};// 伤害不超过 mid 的情况下,能够到达第 n 行
bool bfs(int mid)
{if(n == 1) return true;memset(st, 0, sizeof st);queue<PII> q;// 1. 把所有的源点加入到队列里面for(int j = 1; j <= m; j++){q.push({1, j});st[1][j] = true;}while(q.size()){auto t = q.front(); q.pop();int x = t.first, y = t.second;for(int i = 0; i < 4; i++){int a = x + dx[i], b = y + dy[i];if(a >= 1 && a <= n && b >= 1 && b <= m && p[a][b] <= mid && st[a][b] == false){st[a][b] = true;q.push({a, b});if(a == n) return true;}}}return false;
}int main()
{cin >> n >> m;int l = 0, r = 0;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cin >> p[i][j];r = max(r, p[i][j]);}}// 二分答案while(l < r){int mid = (l + r) / 2;if(bfs(mid)) r = mid;else l = mid + 1;}cout << l << endl;return 0;
}

三、01 BFS

01 BFS 称 双端队列 BFS

在最短路问题中权值 1 也可 0。那,在 BFS 将边 0 扩展出来的点放到队⾸ 1 扩展出来的点放到队尾能保证像普通 BFS 整个队列队⾸到队尾权值单调不下降。

注意:

        不同于普通的 bfs 问题01bfs 问题遍历遇到之前已经遍历过点,有能会到⼀条更优的路线。在候,要注意判断这⼀点。

1. ⼩明的游戏

题⽬来源:洛⾕

题⽬链接:P4554 小明的游戏 - 洛谷

难度系数:★★

(1)题目描述

(2)算法原理

01bfs 模板题

  • ⾛到相同,权值为 0 ,更短距离,然后加⼊到队头
  • ⾛到不同,权值为 0 ,更短距离,然后加⼊到队尾

        其余的搜索与常规 bfs 样,但注意松弛操作

注意

 输入时要从 0 开始,不能从 1 开始,因为给的坐标中可能有 0 ;

(3)参考代码

#include <iostream>
#include <deque>
#include <cstring>using namespace std;typedef pair<int, int> PII;const int N = 510;int n, m, x1, y1, x2, y2;
char a[N][N];
int dist[N][N];int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};void bfs()
{if(x1 == x2 && y1 == y2){dist[x2][y2] = 0;return;}memset(dist, -1, sizeof dist);deque<PII> q;q.push_back({x1, y1});dist[x1][y1] = 0;while(q.size()){auto t = q.front(); q.pop_front();int i = t.first, j = t.second;if(i == x2 && j == y2) return; // 剪枝for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];if(x >= 0 && x < n && y >= 0 && y < m){char cur = a[i][j], next = a[x][y];int w = (cur == next ? 0 : 1);if(dist[x][y] == -1){dist[x][y] = dist[i][j] + w;// 01 BFSif(w == 0) q.push_front({x, y});else q.push_back({x, y});}else if(dist[i][j] + w < dist[x][y]) // 虽然是第二次遇到,但是这种情况更优{// 松弛操作dist[x][y] = dist[i][j] + w;}// if(x == x2 && y == y2) return;}}}
}int main()
{while(cin >> n >> m, n && m){for(int i = 0; i < n; i++)for(int j = 0; j < m; j++)cin >> a[i][j];cin >> x1 >> y1 >> x2 >> y2;bfs();cout << dist[x2][y2] << endl;}return 0;
}

2. ThreeStates

题⽬来源:洛⾕

题⽬链接:CF590C Three States - 洛谷

难度系数:★★★★

(1)题目描述

(2)算法原理

正难则反:

  • 找出结果点烦的,要枚举所有的点,然后每个点都要来⼀次 bfs 超时的。
  • 可以依次从三个家出发 bfs   算出到达所有点的最短距离。求出所之后重新遍历所有的点,况求出到三个的最短距离。

理很简单,但是⾥⾯有很多细节需要注意:

  1. 为每个家可能有很点,并且的点之间不连通,因此我们要 多源bfs  家到所有点的最短距离;
  2. 国家与家之间的点相连之间 0  是不是同⼀个,在这道题⾥⾯,们的离都是 0  ,因不需要修)。那么我这道题⾥⾯边的权值要么是0 ,要么是1 。因此需 01bfs 来更新所有的离;
  3. 计算⼀个到三个的最短距况讨论。设 a, b, 分别表⽰三个家到该点的最短距离:
  •         如果该点是⼀个,最短距离为 a + b + c
    •         如果该点是⼀个荒地,最短距离为 a +b+c−2 ,因为我们计算最短距离的时候,荒地会被计算三次,所以要减去两次。

(3)参考代码

#include <iostream>
#include <deque>
#include <cstring>using namespace std;typedef pair<int, int> PII;const int N = 1010;int n, m;
char a[N][N];
int dist[4][N][N];
// dist[1] dist[2] dist[3]int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};void bfs(int num)
{memset(dist[num], -1, sizeof dist[num]);// 多源bfsdeque<PII> q;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++){if(a[i][j] - '0' == num){q.push_back({i, j});dist[num][i][j] = 0;}}// 01bfswhile(q.size()){auto t = q.front(); q.pop_front();int i = t.first, j = t.second;for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];if(x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] != '#'){int w = (a[x][y] == '.' ? 1 : 0);if(dist[num][x][y] == -1) // 第一次遇到{dist[num][x][y] = dist[num][i][j] + w;if(w) q.push_back({x, y});else q.push_front({x, y});}else if(dist[num][i][j] + w < dist[num][x][y]){dist[num][x][y] = dist[num][i][j] + w;}}}}
}int main()
{cin >> n >> m;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)cin >> a[i][j];bfs(1); bfs(2); bfs(3);int ret = 0x3f3f3f3f;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++){if(a[i][j] == '#') continue;int x = dist[1][i][j], y = dist[2][i][j], z = dist[3][i][j];if(x == -1 || y == -1 || z == -1) continue;if(a[i][j] == '.') ret = min(ret, x + y + z - 2);else ret = min(ret, x + y + z);}if(ret == 0x3f3f3f3f) cout << -1 << endl;else cout << ret << endl;return 0;
}

四、Floodfill 问题

Floodfill 算法,⼜称漫⽔填充,像素法,本质是在寻找具有相同性质的联通块

1. LakeCounting

题⽬来源:洛⾕

题⽬链接:P1596 [USACO10OCT] Lake Counting S - 洛谷

难度系数:★

(1)题目描述

(2)算法原理

遍历整个矩阵,当遇到⼀个没有标记

  • 后⽤ bfs 或者 dfs 将整个都标记⼀下

整个矩阵遍历⼀遍能得湖的数量

(3)参考代码

#include <iostream>
#include <queue>
#include <cstring>using namespace std;const int N = 110;int n, m;
char a[N][N];
bool st[N][N]; // 标记哪些区域已经被搜索过了int dx[] = {0, 0, 1, -1, 1, 1, -1, -1};
int dy[] = {1, -1, 0, 0, 1, -1, 1, -1};void dfs(int i, int j)
{st[i][j] = true;for(int k = 0; k < 8; k++){int x = i + dx[k], y = j + dy[k];if(x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] == 'W' && st[x][y] == false){dfs(x, y);}}
}void bfs(int i, int j)
{queue<pair<int, int>> q;q.push({i, j});st[i][j] = true;while(q.size()){auto t = q.front(); q.pop();int i = t.first, j = t.second;for(int k = 0; k < 8; k++){int x = i + dx[k], y = j + dy[k];if(x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] == 'W' && st[x][y] == false){st[x][y] = true;q.push({x, y});}}}
}int main()
{cin >> n >> m;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)cin >> a[i][j];int ret = 0;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){if(a[i][j] == 'W' && st[i][j] == false){ret++;// dfs(i, j); // 把这块区域打上标记bfs(i, j); // 把这块区域打上标记}}}cout << ret << endl;return 0;
}

2. 填涂颜⾊

题⽬来源:洛⾕

题⽬链接:P1162 填涂颜色 - 洛谷

难度系数:★★

(1)题目描述

(2)算法原理

正难则反

找出 1包围的 0 是很困的,因难确定搜索这个  是否是被的。但是从边缘 0开始搜索,搜索 ⼀定是没有被围的。

从边缘 0 开搜索,标记与边缘  0 相连联通块。那有被标记 0 就是被包围的。

⼩技巧

  • 把整个矩阵围包上⼀层 0 只⽤从 [0, 0] 位置即可不⽤遍历第⼀⾏第⼀列,最后⼀⾏后⼀列

(3)参考代码 

#include <iostream>
#include <cstring>using namespace std;const int N = 35;int n;
int a[N][N];
bool st[N][N]; // 只会标记边缘的 0int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};void dfs(int i, int j)
{st[i][j] = true;for(int k = 0; k < 4; k++){int x = i + dx[k], y = j + dy[k];// 注意此时的边界if(x >= 0 && x <= n + 1 && y >= 0 && y <= n + 1 && a[x][y] == 0 && st[x][y] == 0){dfs(x, y);}}
}int main()
{while(cin >> n){for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)cin >> a[i][j];dfs(0, 0);for(int i = 1; i <= n; i++){for(int j = 1; j <= n; j++){if(a[i][j]) cout << a[i][j] << " ";else if(st[i][j]) cout << 0 << " ";else cout << 2 << " ";}cout << endl;}}return 0;
}
http://www.dtcms.com/wzjs/313827.html

相关文章:

  • 集团酒店网站建设免费发布推广信息的平台
  • 重庆忠县网站建设公司电话免费个人网站注册
  • 旅游做攻略的网站有哪些想建立自己的网站怎么建立
  • 做网站品牌公司刘雯每日资讯
  • 深圳网站制作公司深圳app开发新浪nba最新消息
  • 北京朝阳社会建设工作办公室网站付费内容网站
  • 福田区网站建seo综合查询怎么用
  • 石家庄手机网站制作多少钱企业推广公司
  • 大众点评网怎么做团购网站推广软件哪个好
  • 餐饮加盟网站怎么做推广效果最好的平台
  • 网站怎做网络营销师有前途吗
  • app软件开发公司推荐湛江seo
  • 专业集团门户网站建设费用小程序开发文档
  • 网站页面设计代码seo快速排名首页
  • 百度网站安全检测平台天猫代运营
  • 做网站要实名吗广告推广平台网站有哪些
  • .org做商业网站运营是做什么的
  • 给传销产品做网站nba哈登最新消息
  • 广州网站制作托管做引流的公司是正规的吗
  • 做外汇上什么网站看新闻搜索引擎最新排名
  • 住房和城乡建设部网站 城市绿地分类免费的短视频app大全
  • 用国外服务器做赌博网站搜索引擎优化的流程是什么
  • 网站建设设计维片武汉seo技术
  • 门户网站html武汉seo广告推广
  • 天津做美缝的网站seo整站优化一年价格多少
  • 怎么制作爆米花教程seo专业培训学费多少钱
  • 网站备案号中信息有变营销排名seo
  • 宁波做网站建设五种新型营销方式
  • 定制化网站开发报价2021年热门关键词
  • 最新网站推广推蛙网络