专题一 简单搜索

POJ 1321 棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

直接DFS,遍历所有的可能。因为是一层一层遍历的,所以只要记录每一列有没有出现过就可以

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 1000 + 10;
int n, m;
char map[maxn][maxn];
bool y[maxn];
int sum = 0, tot = 0;void dfs(int x)
{if (x == n) {if (sum == m) {tot++;}return;}dfs(x + 1);for (int i = 0; i < n; i++) {if (map[x][i] == '#' && !y[i]) {y[i] = true;sum++;dfs(x + 1);y[i] = false;sum--;}}
}int main()
{while (1) {tot = 0, sum = 0;memset(y, 0, sizeof(y));scanf("%d%d", &n, &m);if (n == -1)return 0;for (int i = 0; i < n; i++) {scanf("%s", map[i]);}dfs(0);cout << tot << endl;}return 0;
}

POJ 2251 Dungeon Master

你被困在一个三维地牢,需要找到最快的出路!地牢是由单元立方体组成的,这些立方体可能是石头,也可能不是石头。往北、往南、向东、向西、向上或向下移动一个单元需要一分钟。你不能斜着走,迷宫四周都是坚硬的岩石。
有可能逃跑吗?如果可以,需要多长时间?

升级版走迷宫,从两维变成三维,方向从四个方向变成六个方向,直接BFS找最短的路就好

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 42;
int r, n, m;
char map[maxn][maxn][maxn];
int p[maxn][maxn][maxn], tot[maxn][maxn][maxn];
int x1, y1, z1;
int xx[6] = { 1, -1, 0, 0, 0, 0 };
int yy[6] = { 0, 0, 1, -1, 0, 0 };
int zz[6] = { 0, 0, 0, 0, 1, -1 };
struct Point {int x, y, z;
};int bfs(int x, int y, int z)
{memset(p, 0, sizeof(p));memset(tot, 0, sizeof(tot));tot[z][x][y] = 1;queue<Point> q;q.push((Point){ x, y, z });while (!q.empty()) {Point k = q.front();q.pop();for (int i = 0; i < 6; i++) {int x0 = k.x + xx[i];int y0 = k.y + yy[i];int z0 = k.z + zz[i];if (x0 >= 0 && x0 < n && y0 >= 0 && y0 < m && z0 >= 0 && z0 < r && map[z0][x0][y0] != '#' && !tot[z0][x0][y0]) {tot[z0][x0][y0] = 1;p[z0][x0][y0] = p[k.z][k.x][k.y] + 1;q.push((Point){ x0, y0, z0 });if (map[z0][x0][y0] == 'E') {return p[z0][x0][y0];}}}}return -1;
}int main()
{while (1) {scanf("%d%d%d", &r, &n, &m);if (n == 0 && r == 0 && m == 0)return 0;for (int k = 0; k < r; k++) {for (int i = 0; i < n; i++) {scanf("%s", map[k][i]);for (int j = 0; j < m; j++) {if (map[k][i][j] == 'S') {x1 = i;y1 = j;z1 = k;}}}}int l = bfs(x1, y1, z1);if (l == -1)printf("Trapped!\n");elseprintf("Escaped in %d minute(s).\n", l);}return 0;
}

POJ 3278 Catch That Cow

农场主约翰已被告知一头逃跑的母牛的位置,他想立即抓住她。它从数轴上的点N开始,牛在同一数轴上的点K开始。农夫约翰有两种交通方式:步行和心灵运输。
*步行:FJ可以在一分钟内从X点移动到X - 1或X + 1点
*心灵移植:FJ可以在一分钟内从任意X点移动到2×X点。
如果这头牛根本不知道自己在追它,不动的话,农夫约翰要多久才能把它找回来?

BFS遍历所有的情况求最优解,不过要考虑FJ可以到达最远的距离防止TL。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;const int maxn = 200000 + 100;
int n, m;
bool vis[maxn];
int p[maxn], t;int bfs(int x)
{queue<int> q;vis[x] = true;q.push(x);while (!q.empty()) {int k = q.front();q.pop();t = k + 1;if (t >= 0 && t <= 150000 && !vis[t]) {vis[t] = true;p[t] = p[k] + 1;q.push(t);if (t == m)return p[t];}t = k - 1;if (t >= 0 && t <= 150000 && !vis[t]) {vis[t] = true;p[t] = p[k] + 1;q.push(t);if (t == m)return p[t];}t = k * 2;if (t >= 0 && t <= 150000 && !vis[t]) {vis[t] = true;p[t] = p[k] + 1;q.push(t);if (t == m)return p[t];}}return 0;
}int main()
{cin >> n >> m;int l = bfs(n);cout << l << endl;return 0;
}

POJ 3279 Fliptile

农夫约翰知道一头智力满足的奶牛是一头快乐的奶牛,它会产更多的牛奶。他为奶牛安排了一项脑力活动,让它们操纵一个M×N的网格(1≤M≤15;1≤N≤15)方片,每方片一面为黑色,另一面为白色。
正如人们所猜测的,当一块白色瓷砖翻转时,它会变成黑色;当翻转一个黑色的瓦片时,它会变成白色。当奶牛翻转瓷砖时,它们会得到奖励,这样每块瓷砖都有一面朝上的白色。然而,奶牛的蹄子相当大,当它们试图翻转某个瓦片时,它们也会翻转所有相邻的瓦片(与翻转瓦片共享完整边缘的瓦片)。由于抛硬币很累人,奶牛们想把抛硬币的次数降到最低。
帮助奶牛确定所需翻转的最少次数,以及要翻转到最少的位置。如果有多种方法可以用最少的投掷次数来完成任务,那么当将输出视为字符串时,返回字典排序最少的方法。如果任务不可能完成,打印一行“不可能”。

翻瓷砖问题,每次翻一个之后,前后左右四个方向的瓷砖也会被翻过.
先不考虑第一列,在第二列中为了让第一列全为正,所以应该把第一列为反的瓷砖的下面的进行反转,以此类推,直到最后一列,若最后最后一列全为正则合理,否则不合理,所以只要第一列确定了后面的结果就确定了,所以只要把第一列的所以情况枚举出来就可以。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;const int maxn = 100;
int map[maxn][maxn], p[maxn], q[maxn][maxn], t[maxn][maxn], lll[maxn][maxn];
int n, m;void Put(int x, int y)
{int xx[5] = { 0, 0, 0, 1, -1 };int yy[5] = { 1, -1, 0, 0, 0 };for (int i = 0; i < 5; i++) {int x0 = x + xx[i];int y0 = y + yy[i];if (x0 >= 0 && y0 >= 0 && x0 < n && y0 < m) {q[x0][y0] ^= 1;}}
}int work()
{int sum = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {q[i][j] = map[i][j];}}for (int i = 0; i < m; i++) {if (p[i]) {Put(0, i);sum++;t[0][i] = 1;}}for (int i = 1; i < n; i++) {for (int j = 0; j < m; j++) {if (q[i - 1][j]) {Put(i, j);sum++;t[i][j] = 1;}}}for (int i = 0; i < m; i++) {if (q[n - 1][i])return -1;}return sum;
}int main()
{scanf("%d%d", &n, &m);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {scanf("%d", &map[i][j]);}}int flag = 0, maxx = 1e9;for (int i = 0; i < (1 << m); i++) {memset(p, 0, sizeof(p));memset(t, 0, sizeof(t));for (int j = 0; j < m; j++) {if ((1 << j) & i)p[j] = 1;}int l = work();if (l != -1) {flag = 1;if (l < maxx) {maxx = l;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {lll[i][j] = t[i][j];}}}}}if (!flag) {cout << "IMPOSSIBLE" << endl;} else {for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {printf("%d ", lll[i][j]);}cout << endl;}}return 0;
}

POJ 1426 Find The Multiple

给定一个正整数n,编写一个程序找出一个n的非零倍数m,其十进制表示仅包含数字0和1。您可以假设n不大于200,并且对应的m包含不超过100位小数。

直接暴力枚举所有的0,1情况从1开始每次×10,或者×10+1,得到的数对n取模就可以

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
#define ll long longvoid bfs(int n)
{queue<ll> q;q.push(1);while (!q.empty()) {ll k = q.front();if (k % n == 0) {cout << k << endl;return;}q.pop();q.push(k * 10);q.push(k * 10 + 1);}return;
}int main()
{int n;while (scanf("%d", &n), n) {bfs(n);}return 0;
}

POJ 3126 Prime Path

-事实上,我有。你看,有一场编程比赛正在进行……帮助总理在任意两个给定的四位素数之间找到最便宜的素数路径!当然,第一个数字必须是非零的。在上面的例子中有一个解。
1033
1733
3733
3739
3779
8779
8179
这个解决方案的成本是6英镑。注意,第2步中粘贴的数字1不能在最后一步中重用——必须购买一个新的1。

直接暴力枚举每一位的情况,如果是素数就继续遍历直到找到另一个素数。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;int T, sum;
int aa, bb;
bool vis[10000];
struct node {int x, cnt;
};bool pd(int x)
{if (x == 0 || x == 1)return false;for (int i = 2; i * i <= x; i++) {if (x % i == 0)return false;}return true;
}int bfs(int x, int cnt)
{queue<node> q;q.push((node){ x, cnt });vis[x] = true;if (x == bb) {return 0;}while (!q.empty()) {node k = q.front();q.pop();for (int i = 0; i <= 9; i++) {int a = k.x % 10;int b = (k.x / 10) % 10;int c = (k.x / 100) % 10;int d = (k.x / 1000) % 10;int t1 = (((((i * 10) + c) * 10) + b) * 10) + a;if (pd(t1) && !vis[t1] && i != 0) {vis[t1] = true;q.push((node){ t1, k.cnt + 1 });if (t1 == bb) {return k.cnt + 1;}}t1 = (((((d * 10) + i) * 10) + b) * 10) + a;if (pd(t1) && !vis[t1]) {vis[t1] = true;q.push((node){ t1, k.cnt + 1 });if (t1 == bb) {return k.cnt + 1;}}t1 = (((((d * 10) + c) * 10) + i) * 10) + a;if (pd(t1) && !vis[t1]) {vis[t1] = true;q.push((node){ t1, k.cnt + 1 });if (t1 == bb) {return k.cnt + 1;}}t1 = (((((d * 10) + c) * 10) + b) * 10) + i;if (pd(t1) && !vis[t1]) {vis[t1] = true;q.push((node){ t1, k.cnt + 1 });if (t1 == bb) {return k.cnt + 1;}}}}return -1;
}int main()
{cin >> T;while (T--) {memset(vis, 0, sizeof(vis));scanf("%d%d", &aa, &bb);int l = bfs(aa, 0);if (l == -1)cout << "Impossible" << endl;elsecout << l << endl;}return 0;
}

POJ 3087 Shuffle’m Up

扑克玩家在牌桌上最常见的消遣就是洗牌。洗牌筹码由两堆扑克筹码开始,分别是S1和S2,每堆都包含C个筹码。每个堆栈可以包含几种不同颜色的芯片。
实际的shuffle操作是将S1的芯片与S2的芯片交叉,如下图所示,C = 5:

单个结果堆栈S12包含2 * C芯片。S12的底端芯片是S2的底端芯片。在那个芯片的上面,是S1的最下面的芯片。交叉过程继续从S2的底部取出第二个芯片并将其放置在S12上,然后从S1的底部取出第二个芯片,以此类推,直到S1的顶部芯片被放置在S12上。
洗牌操作后,将S12分成两个新的栈,从S12中取出最底层的C片形成一个新的S1,从S12中取出顶层的C片形成一个新的S2。然后可以重复洗牌操作以形成一个新的S12。
对于这个问题,您将编写一个程序来确定一个特定的结果堆栈S12是否可以通过将两个堆栈打乱若干次来形成。

直接遍历所有洗牌后的状态即可

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
using namespace std;
const int maxn = 2000 + 100;
int T;
int n, minn, sum;
string a, b, c;
map<string, bool> q;void dfs()
{string t;for (int i = 0; i < n; i++) {t += b[i];t += a[i];}if (t == c) {minn = min(sum, minn);return;}if (!q[t]) {q[t] = true;a = "";b = "";for (int i = 0; i < n; i++) {a += t[i];}for (int i = 0; i < n; i++) {b += t[i + n];}sum++;dfs();}
}int main()
{cin >> T;for (int lll = 1; lll <= T; lll++) {minn = 1e9;cin >> n;cin >> a >> b >> c;q.clear();sum = 1;dfs();if (minn == 1e9)printf("%d -1\n", lll);elseprintf("%d %d\n", lll, minn);}return 0;
}

POJ 3414 Pots

你有两个壶,分别有A和B升的体积。可以执行以下操作:

  1. FILL(i) 从水龙头往i(1≤i≤2)罐内灌满;
  2. DROP(i) 把锅里的水倒进排水沟里;
  3. POUR(i,j) 从锅i倒到锅j;在这个操作之后,要么锅j满了(可能锅i中还剩下一些水),要么锅i是空的(它的所有内容都被移到了锅j中)。

编写一个程序,找出这些操作中最短的可能顺序,使其中一个罐子刚好能产生C公升的水。

BFS 枚举每种变化,记录最短的路径,其实不是很难就是写起来比较复杂而已

#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;int a, b, c, xx, yy;
struct E {int x, y, cnt;
};
struct p {int x, y, o;
} e[1000][1000];
bool vis[1000][1000];
int bfs()
{queue<E> q;q.push((E){ 0, 0, 0 });vis[0][0] = true;while (!q.empty()) {E k = q.front();if (k.x == c || k.y == c) {xx = k.x, yy = k.y;return k.cnt;}q.pop();int x, y;x = 0;y = k.y;if (!vis[x][y]) {e[x][y] = (p){ k.x, k.y, 1 };vis[x][y] = true;q.push((E){ x, y, k.cnt + 1 });}x = k.x;y = 0;if (!vis[x][y]) {e[x][y] = (p){ k.x, k.y, 2 };vis[x][y] = true;q.push((E){ x, y, k.cnt + 1 });}x = a;y = k.y;if (!vis[x][y]) {e[x][y] = (p){ k.x, k.y, 3 };vis[x][y] = true;q.push((E){ x, y, k.cnt + 1 });}x = k.x;y = b;if (!vis[x][y]) {e[x][y] = (p){ k.x, k.y, 4 };vis[x][y] = true;q.push((E){ x, y, k.cnt + 1 });}if (k.x > b - k.y) {x = k.x - (b - k.y);y = b;} else {x = 0;y = k.y + k.x;}if (!vis[x][y]) {e[x][y] = (p){ k.x, k.y, 5 };vis[x][y] = true;q.push((E){ x, y, k.cnt + 1 });}if (k.y > a - k.x) {x = a;y = k.y - (a - k.x);} else {x = k.y + k.x;y = 0;}if (!vis[x][y]) {e[x][y] = (p){ k.x, k.y, 6 };vis[x][y] = true;q.push((E){ x, y, k.cnt + 1 });}}return -1;
}void print(int x, int y)
{if (x == 0 && y == 0)return;print(e[x][y].x, e[x][y].y);switch (e[x][y].o) {case 1:cout << "DROP(1)";break;case 2:cout << "DROP(2)";break;case 3:cout << "FILL(1)";break;case 4:cout << "FILL(2)";break;case 5:cout << "POUR(1,2)";break;case 6:cout << "POUR(2,1)";break;default:break;}cout << endl;
}int main()
{cin >> a >> b >> c;int l = bfs();if (l == -1)cout << "impossible" << endl;else {cout << l << endl;print(xx, yy);}
}

FZU 2150 Fire Game

胖哥和迷宫在一个N*M的棋盘(N行,M列)上玩一种特殊的(hentai)游戏。开始的时候,每个格子都是草或者是空的然后他们开始点燃所有的草。首先,他们选择由草和火组成的两个网格。我们都知道,火可以在草地上蔓延。如果网格(x, y)在t时刻触发,则与此网格相邻的网格将在t+1时刻触发,t+1表示网格(x+1, y) (x, y+1) (x, y+1) (x, y+1) (x, y) (x, y+1) (x, y) (x, y) (x, y)这个过程结束时,没有新的网格得到火。如果所有由草组成的格子都被烧坏了,胖哥和迷宫就会站在格子中间,玩一个更特别的(hentai)游戏。(也许是在最后一个问题中解密的OOXX游戏,谁知道呢。)
你可以假设木板上的草永远不会烧完,空格子永远不会着火。
注意,他们选择的两个网格可以是相同的。

点火问题,选择两个点开始BFS,求最短的时间。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 200 + 10;
int T, n, m;
char map[maxn][maxn];
int vis[maxn][maxn];
int xx[4] = { 1, -1, 0, 0 };
int yy[4] = { 0, 0, 1, -1 };
int x1, x2, y1, y2;
struct Point {int x, y;
} e[maxn];
int tot = 0, cnt;
int dfs(int a, int b)
{cnt = 1;queue<Point> q;q.push((Point){ e[a].x, e[a].y });q.push((Point){ e[b].x, e[b].y });vis[e[a].x][e[a].y] = 1;vis[e[b].x][e[b].y] = 1;while (!q.empty()) {Point k = q.front();q.pop();for (int i = 0; i < 4; i++) {int x0 = k.x + xx[i];int y0 = k.y + yy[i];if (x0 >= 0 && x0 < n && y0 >= 0 && y0 < m && map[x0][y0] == '#' && !vis[x0][y0]) {vis[x0][y0] = vis[k.x][k.y] + 1;q.push((Point){ x0, y0 });cnt = max(cnt, vis[x0][y0]);}}}return cnt;
}
int main()
{cin >> T;for (int ll = 1; ll <= T; ll++) {tot = 0;scanf("%d%d", &n, &m);for (int i = 0; i < n; i++) {scanf("%s", map[i]);for (int j = 0; j < m; j++) {if (map[i][j] == '#') {e[++tot].x = i;e[tot].y = j;}}}int sum = 1e9;for (int i = 1; i <= tot; i++) {for (int j = i; j <= tot; j++) {memset(vis, 0, sizeof(vis));int lll = dfs(i, j);int flag = 0;for (int k = 0; k < n; k++) {for (int l = 0; l < m; l++) {if (map[k][l] == '#' && !vis[k][l]) {flag = 1;break;}if (flag)break;}}if (!flag)sum = min(sum, lll - 1);}}if (sum == 1e9)printf("Case %d: -1\n", ll);elseprintf("Case %d: %d\n", ll, sum);}return 0;
}

UVA 11624 Fire!

乔在迷宫里工作。不幸的是,迷宫的部分区域有着火了,迷宫的主人忘记生火了逃跑计划。帮助乔逃离迷宫。给定乔在迷宫中的位置和迷宫的哪个方块是着火了,你必须先确定乔是否能逃出迷宫火到达了他的身边,他能以多快的速度做到这一点。乔和火每分钟移动一个正方形,垂直或水平(不是对角)。大火向四面八方蔓延从每一个着火的广场。乔可以从任何一个迷宫中出迷宫边缘的正方形。既不是乔也不是火可以进入一个被墙占据的广场。

两次遍历,第一次求出火蔓延到各个点的时间,第二次在着火的约束下求走出迷宫的最短时间。注意着火点不止有有一个。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 1000 + 10;
int n, m, T, ttt;
int x1, y1, x2[maxn], y2[maxn], vis[maxn][maxn];
char map[maxn][maxn];
int xx[4] = { 1, -1, 0, 0 };
int yy[4] = { 0, 0, 1, -1 };
struct Point {int x, y;
};
bool tot[maxn][maxn];
void bfs()
{memset(tot, 0, sizeof(tot));queue<Point> q;for (int i = 1; i <= ttt; i++) {q.push((Point){ x2[i], y2[i] });tot[x2[i]][y2[i]] = 1;vis[x2[i]][y2[i]] = 1;}while (!q.empty()) {Point k = q.front();q.pop();for (int i = 0; i < 4; i++) {int x0 = k.x + xx[i];int y0 = k.y + yy[i];if (x0 >= 0 && x0 < n && y0 >= 0 && y0 < m && map[x0][y0] != '#' && !tot[x0][y0]) {tot[x0][y0] = 1;vis[x0][y0] = vis[k.x][k.y] + 1;q.push((Point){ x0, y0 });}}}
}
int p[maxn][maxn];
int bfs2(int x, int y)
{memset(p, 0, sizeof(p));tot[x][y] = 1;memset(tot, 0, sizeof(tot));p[x][y] = 1;queue<Point> q;q.push((Point){ x, y });if (x == 0 || y == 0 || x == n - 1 || y == m - 1)return 1;while (!q.empty()) {Point k = q.front();q.pop();for (int i = 0; i < 4; i++) {int x0 = k.x + xx[i];int y0 = k.y + yy[i];if (x0 >= 0 && x0 < n && y0 >= 0 && y0 < m && map[x0][y0] != '#' && !tot[x0][y0] && (p[k.x][k.y] + 1 < vis[x0][y0] || !vis[x0][y0])) {tot[x0][y0] = 1;p[x0][y0] = p[k.x][k.y] + 1;q.push((Point){ x0, y0 });if (x0 == 0 || y0 == 0 || x0 == n - 1 || y0 == m - 1)return p[x0][y0];}}}return -1;
}int main()
{scanf("%d", &T);while (T--) {memset(vis, 0, sizeof(vis));scanf("%d%d", &n, &m);ttt = 0;for (int i = 0; i < n; i++) {scanf("%s", map[i]);for (int j = 0; j < m; j++) {if (map[i][j] == 'J') {x1 = i, y1 = j;}if (map[i][j] == 'F') {x2[++ttt] = i, y2[ttt] = j;}}}bfs();int t = bfs2(x1, y1);if (t == -1)cout << "IMPOSSIBLE" << endl;elsecout << t << endl;}return 0;
}

POJ 3984 迷宫问题

定义一个二维数组:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

BFS求最短路,并记录最短路的路径

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 10;
int map[maxn][maxn], tot = 1;
int vis[maxn][maxn], p[maxn][maxn], x[maxn], y[maxn];
int xx[4] = { 1, 0, 0, -1 };
int yy[4] = { 0, -1, 1, 0 };
struct Point {int x, y;
};
void bfs(int a, int b)
{queue<Point> q;q.push((Point){ a, b });while (!q.empty()) {Point k = q.front();q.pop();for (int i = 0; i < 4; i++) {int x0 = k.x + xx[i];int y0 = k.y + yy[i];if (x0 >= 0 && x0 < 5 && y0 >= 0 && y0 < 5 && map[x0][y0] == 0 && !vis[x0][y0]) {vis[x0][y0] = 1;p[x0][y0] = 3 - i;q.push((Point){ x0, y0 });if (x0 == 4 && y0 == 4)return;}}}
}
void dfs(int ax, int ay)
{if (ax == 0 && ay == 0)return;x[++tot] = ax + xx[p[ax][ay]];y[tot] = ay + yy[p[ax][ay]];dfs(x[tot], y[tot]);
}
int main()
{for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++) {scanf("%d", &map[i][j]);}}bfs(0, 0);dfs(4, 4);x[1] = 4, y[1] = 4;for (int i = tot; i > 0; i--) {printf("(%d, %d)\n", x[i], y[i]);}return 0;
}

HDU 1241 Oil Deposits

地质urvcomp地质勘测公司负责探测地下油层。GeoSurvComp每次处理一个大的矩形区域,并创建一个网格,将土地划分为许多方形地块。然后用传感设备分别分析每个地块,以确定该地块是否含有石油。一块含有石油的土地叫做口袋。如果两个储层相邻,则它们属于同一油层的一部分。石油储量可以相当大,可能包含许多口袋。你的工作是确定有多少不同的石油蕴藏在一个网格。

寻找地图中有多少联通块,直接遍历把遍历过的点改为*即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 100 + 10;
int n, m, sum;
char map[maxn][maxn];
bool vis[maxn][maxn];
int xx[8] = { 1, -1, 0, 0, 1, 1, -1, -1 };
int yy[8] = { 0, 0, 1, -1, 1, -1, 1, -1 };
void dfs(int x, int y)
{map[x][y] = '*';for (int i = 0; i < 8; i++) {int x0 = x + xx[i];int y0 = y + yy[i];if (x >= 0 && x < n && y >= 0 && y < m && map[x0][y0] == '@') {dfs(x0, y0);}}
}
int main()
{while (1) {memset(vis, 0, sizeof(vis));scanf("%d%d", &n, &m);sum = 0;if (n == 0)return 0;for (int i = 0; i < n; i++) {scanf("%s", map[i]);}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (map[i][j] == '@') {dfs(i, j);sum++;}}}printf("%d\n", sum);}return 0;
}

HDU 1495 非常可乐

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

简单的模拟暴力,但在条件处理是要注意,容易出现错误

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;const int maxn = 200;
int b[3];
bool vis[maxn][maxn][maxn];struct E {int val[3], cnt;
};bool pd(int tt[3])
{int t = b[0] / 2;if ((tt[0] == t && tt[1] == t) || (tt[2] == t && tt[1] == t) || (tt[0] == t && tt[2] == t))return true;return false;
}int bfs()
{E aa;aa.val[0] = b[0], aa.val[1] = 0, aa.val[2] = 0;aa.cnt = 0;queue<E> q;q.push(aa);memset(vis, 0, sizeof(vis));vis[b[0]][0][0] = true;while (!q.empty()) {E k = q.front();q.pop();for (int i = 0; i < 3; i++) {if (k.val[i])for (int j = 0; j < 3; j++) {if (i == j)continue;E pp = k;pp.cnt++;if (k.val[i] > b[j] - k.val[j]) {pp.val[i] -= b[j] - k.val[j];pp.val[j] = b[j];} else {pp.val[i] = 0;pp.val[j] += k.val[i];}if (!vis[pp.val[0]][pp.val[1]][pp.val[2]]) {vis[pp.val[0]][pp.val[1]][pp.val[2]] = true;q.push(pp);if (pd(pp.val)) {return pp.cnt;}}}}}return -1;
}int main()
{while (scanf("%d%d%d", &b[0], &b[1], &b[2]), b[1] + b[0] + b[2]) {if (b[0] % 2 == 1)printf("NO\n");else {int l = bfs();if (l == -1)printf("NO\n");elseprintf("%d\n", l);}}return 0;
}

HDU 2612 Find a way

ass在杭州学习了一年,终于抵达家乡宁波。离开宁波一年,依芬飞有很多人要见面。尤其是好朋友梅尔斯基。
一芬飞的家在乡下,但奔驰的家在市中心。于是易芬飞和奔驰约好在肯德基见面。宁波有很多肯德基,他们想选择一个让总时间最小的。
现在给你一张宁波地图,一芬飞和奔驰都可以上下左右移动到相邻的路上,只需要11分钟。

两次BFS,求出每个人到每个KFC的最短距离。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;const int maxn = 200 + 10;
int n, m, sum;
char map[maxn][maxn];
int vis[maxn][maxn], vis2[maxn][maxn];
int xx[4] = { 1, -1, 0, 0 };
int yy[4] = { 0, 0, 1, -1 };
int x1, x2, y1, y2;
struct Point {int x, y;
};void bfs(int x, int y, int t)
{bool tot[maxn][maxn];int ttt = 0;memset(tot, 0, sizeof(tot));tot[x][y] = 1;queue<Point> q;q.push((Point){ x, y });while (!q.empty()) {Point k = q.front();q.pop();for (int i = 0; i < 4; i++) {int x0 = k.x + xx[i];int y0 = k.y + yy[i];if (x0 < 0 || x0 >= n || y0 < 0 || y0 >= m || map[x0][y0] == '#' || tot[x0][y0])continue;if (t)vis[x0][y0] = vis[k.x][k.y] + 1;elsevis2[x0][y0] = vis2[k.x][k.y] + 1;tot[x0][y0] = 1;q.push((Point){ x0, y0 });}}
}int main()
{while (~scanf("%d%d", &n, &m)) {sum = 0;memset(vis, 0, sizeof(vis));memset(vis2, 0, sizeof(vis2));for (int i = 0; i < n; i++) {scanf("%s", map[i]);for (int j = 0; j < m; j++) {if (map[i][j] == 'Y')x1 = i, y1 = j;if (map[i][j] == 'M')x2 = i, y2 = j;if (map[i][j] == '@')sum++;}}bfs(x1, y1, 0);bfs(x2, y2, 1);int minn = 1e9;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (map[i][j] == '@' && vis[i][j] && vis2[i][j]) {minn = min(minn, (vis[i][j] + vis2[i][j]) * 11);}}}printf("%d\n", minn);}return 0;
}

[kuangbin带你飞]专题1相关推荐

  1. kuangbin带你飞专题合集

    题目列表 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题二 搜索进阶 [kuangbin带你飞]专题三 Dancing Links [kuangbin带你飞]专题四 最短路 ...

  2. “kuangbin带你飞”专题计划——专题十四:数论基础

    写在前面 1.目前还没啥写的.开始时间:2021-05-13(其实博客上看得到该博客创建时间的) 2.上一个专题刷的是网络流(博客总结),属于第一次接触.本来想的是一周特别高效,然后一周略划水,结果是 ...

  3. (2021-07-14~)“kuangbin带你飞”专题计划——专题十三:基础计算几何

    目录 前言 参考博客 自己总结的东西: 难度判断? 题目 1.[TOYS POJ - 2318 ](解决) 2.[Toy Storage POJ - 2398 ](解决) 3.[Segments PO ...

  4. [kuangbin带你飞]专题十二 基础DP1 题解+总结

    kuangbin带你飞:点击进入新世界 总结: 简单dp,最近在做,持续更新. 文章目录 总结: 1.Max Sum Plus Plus 2.Ignatius and the Princess IV ...

  5. kuangbin带你飞 专题1-23 题单

    kuangbin大神,对于打过ACM比赛的ACMer,无人不知无人不晓. 在此,附上vjudge平台上一位大神整理的[kuangbin带你飞]专题目录链接. [kuangbin带你飞专题目录1-23] ...

  6. [kuangbin带你飞]专题五 并查集 题解+总结

    kuangbin带你飞:点击进入新世界 总结: 本人算是初学者中的初学者,欢迎交流~ 并查集的接触过的不多,大概只有普通并查集,带权并查集,种族并查集,传说中的可持续化并查集只是听说过还没有接触,不过 ...

  7. [kuangbin带你飞]专题五查并集

    写了几个查并集得题,成功把自己写晕了 之后写下面得题(写不下去了) **poj-2912 poj 文章目录 1.POJ - 1611(模板题) 2.HDU - 1213(模板题) 3.poj2236( ...

  8. kuangbin带你飞 专题一

    kuangbin在vjudge上面挂了一些专题,感谢bin神带我飞~ Problem APOJ1321 中文题目 DFS 注意某一行可以不放棋子,因此需要在DFS函数后面加一个dfs(row+1,nu ...

  9. [kuangbin带你飞]专题一 做题顺序与题解 【简单搜索】

    随便说点: 博主正在刷kuangbin专题的题目,初学者,没接触过什么算法,刷题的初衷是备战蓝桥杯,后来发现了算法资料大多是针对acm的,挑选kuangbin专题入门也是如此,毕竟这样分类看起来比较有 ...

最新文章

  1. springCloud学习笔记系列(1)-负载均衡Ribbon
  2. linux 虚拟机新增磁盘,linux(虚拟机)下新增磁盘配置
  3. Matlab图像剪切,超出图像区域指定颜色填充
  4. 模块-import导入时指定别名
  5. opencv+resize+padding+concate
  6. 估值飙至 280 亿美元,Databricks G 轮融资 10 亿美元,谁说开源不挣钱?
  7. pytorch学习:运行Mask R-CNN例程
  8. java的百度编辑器插件下载安装_ueditor-extend
  9. 139邮箱java版,139邮箱登录及发送短信
  10. QT绘制不规则多边形
  11. Interpolator插值器
  12. 利用R包ggmsa进行多序列比对_2020-05-31
  13. 算法题-排列组合问题
  14. 102-并发编程详解(中篇)
  15. MIT计算机专业本硕连读几年,麻省理工一般读几年?
  16. 深信服上网行为管理如何配置双因素/双因子(2FA)身份认证
  17. 某公司申请到一个C类IP地址,但要连接6个的子公司,最大的一个子公司有 26台计算机,每个子公司在一个网段中,则子网掩码应设为?
  18. 解决 Chrome 主页被 duba 劫持问题——干掉钩子
  19. 有点后悔选择了计算机专业!现在学编程,当程序员还有前途吗?
  20. 括苍山观云海风车 迎第一缕曙光

热门文章

  1. 看英文数据手册必备之——Copy Translator
  2. 2021年偃师一高高考成绩查询,2021洛阳市地区高考成绩排名查询,洛阳市高考各高中成绩喜报榜单...
  3. 计算机运维技术指标,电子运维系统结构分析及系统性能指标 - 全文
  4. 手机QQ公众号亿级消息实时群发架构
  5. 【YMGJ】很激动的一刻:将时间显示出来
  6. PowerBuilder 输入框中输入完数据 按回车把相应的数据显示在数据窗口中
  7. 常用传感器讲解十五--触摸传感器(KY-036)
  8. 找出一个二维数组中的鞍点
  9. 【SVN】SVN的基本操作
  10. linux 上查询cache 大小的方法