搜索( d f s , b f s dfs, bfs dfs,bfs )
P1443 马的遍历
题目描述
有一个 n × m n \times m n×m 的棋盘,在某个点 ( x , y ) (x, y) (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n , m , x , y n, m, x, y n,m,x,y。
输出格式
一个 n × m n \times m n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 − 1 -1 −1)。
输入输出样例 #1
输入 #1
3 3 1 1
输出 #1
0 3 2
3 -1 1
2 1 4
说明/提示
数据规模与约定
对于全部的测试点,保证 1 ≤ x ≤ n ≤ 400 1 \leq x \leq n \leq 400 1≤x≤n≤400, 1 ≤ y ≤ m ≤ 400 1 \leq y \leq m \leq 400 1≤y≤m≤400。
b f s bfs bfs
一道 b f s bfs bfs 的模板题,先把马最先的位置压入队列,弹出后再压入所有马走一步能到的地方,如果之前已经到达过了这个地方就不重复压入。
最后注意有五格场宽。
#include<bits/stdc++.h>
using namespace std;
int n, m;
int x, y;
int a[402][402];
int xx[8] = { -1,-2,-2,-1,1,2,2,1 };
int yy[8] = { 2,1,-1,-2,-2,-1,1,2 };
struct node {
int x, y;
};
queue<node>q;
int main() {
cin >> n >> m >> x >> y;
memset(a, -1, sizeof(a));
a[x][y] = 0;
q.push({ x,y });
while (!q.empty()) {
int x1 = q.front().x;
int y1 = q.front().y;
q.pop();
for (int i = 0; i < 8; i++) {
int x2 = x1 + xx[i];
int y2 = y1 + yy[i];
if (x2 > 0 && x2 <= n && y2 > 0 && y2 <= m && a[x2][y2] == -1) {
a[x2][y2] = a[x1][y1] + 1;
q.push({ x2,y2 });
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << setw(5) << a[i][j];
}
cout << endl;
}
return 0;
}
P2895 [USACO08FEB] Meteor Shower S
题目描述
贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星摧毁的地方)。
如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。
根据预报,一共有 M M M 颗流星 ( 1 ≤ M ≤ 50 , 000 ) (1\leq M\leq 50,000) (1≤M≤50,000) 会坠落在农场上,其中第 i i i 颗流星会在时刻 T i T_i Ti( 0 ≤ T i ≤ 1000 0 \leq T _ i \leq 1000 0≤Ti≤1000)砸在坐标为 ( X i , Y i ) ( 0 ≤ X i ≤ 300 (X_i,Y_i)(0\leq X_i\leq 300 (Xi,Yi)(0≤Xi≤300, 0 ≤ Y i ≤ 300 ) 0\leq Y_i\leq 300) 0≤Yi≤300) 的格子里。流星的力量会将它所在的格子,以及周围 4 4 4 个相邻的格子都化为焦土,当然贝茜也无法再在这些格子上行走。
贝茜在时刻 0 0 0 开始行动,她只能在会在横纵坐标 X , Y ≥ 0 X,Y\ge 0 X,Y≥0 的区域中,平行于坐标轴行动,每 1 1 1 个时刻中,她能移动到相邻的(一般是 4 4 4 个)格子中的任意一个,当然目标格子要没有被烧焦才行。如果一个格子在时刻 t t t 被流星撞击或烧焦,那么贝茜只能在 t t t 之前的时刻在这个格子里出现。 贝茜一开始在 ( 0 , 0 ) (0,0) (0,0)。
请你计算一下,贝茜最少需要多少时间才能到达一个安全的格子。如果不可能到达输出 − 1 −1 −1。
输入格式
共 M + 1 M+1 M+1 行,第 1 1 1 行输入一个整数 M M M,接下来的 M M M 行每行输入三个整数分别为 X i , Y i , T i X_i, Y_i, T_i Xi,Yi,Ti。
输出格式
贝茜到达安全地点所需的最短时间,如果不可能,则为 − 1 -1 −1。
输入输出样例 #1
输入 #1
4
0 0 2
2 1 2
1 1 2
0 3 5
输出 #1
5
也是一道 b f s bfs bfs ,每次移动时检查一下下一步会不会被陨石砸到,除此之外就是一道板子题
#include<bits/stdc++.h>
using namespace std;
int a[302][302];
int b[302][302];
int n;
struct drop {
int x, y, t;
}m[50005];
struct node {
int x, y, t;
};
int xb[4] = { -1, 0, 1, 0 };
int yb[4] = { 0, -1, 0, 1 };
int t1 = 0;
queue<node>q;
int main() {
cin >> n;
memset(a, -1, sizeof(a));
for (int i = 0; i < n; i++) {
cin >> m[i].x >> m[i].y >> m[i].t;
}
for (int i = 0; i < n; i++) {
int xx = m[i].x;
int yy = m[i].y;
int tt = m[i].t;
if (a[xx][yy] == -1)a[xx][yy] = tt;
else a[xx][yy] = min(a[xx][yy], tt);
for (int j = 0; j < 4; j++) {
int xxx = xx + xb[j];
int yyy = yy + yb[j];
if (xxx >= 0 && yyy >= 0){
if (a[xxx][yyy] == -1)a[xxx][yyy] = tt;
else a[xxx][yyy] = min(a[xxx][yyy], tt);
}
}
}
q.push({ 0, 0 ,0 });
b[0][0] = 1;
while (!q.empty()) {
int x2 = q.front().x;
int y2 = q.front().y;
int t2 = q.front().t;
q.pop();
if (a[x2][y2] == -1) {
cout << t2;
return 0;
}
for (int i = 0; i < 4; i++) {
int x3 = x2 + xb[i];
int y3 = y2 + yb[i];
int t3 = t2 + 1;
if (x3 >= 0 && y3 >= 0 && (t3 < a[x3][y3] || a[x3][y3] == -1) && !b[x3][y3]) {
q.push({ x3,y3,t3 });
b[x3][y3] = t3;
}
}
}
cout << -1;
return 0;
}
P1036 [NOIP 2002 普及组] 选数
题目描述
已知 n n n 个整数 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn,以及 1 1 1 个整数 k k k( k < n k<n k<n)。从 n n n 个整数中任选 k k k 个整数相加,可分别得到一系列的和。例如当 n = 4 n=4 n=4, k = 3 k=3 k=3, 4 4 4 个整数分别为 3 , 7 , 12 , 19 3,7,12,19 3,7,12,19 时,可得全部的组合与它们的和为:
3 + 7 + 12 = 22 3+7+12=22 3+7+12=22
3 + 7 + 19 = 29 3+7+19=29 3+7+19=29
7 + 12 + 19 = 38 7+12+19=38 7+12+19=38
3 + 12 + 19 = 34 3+12+19=34 3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数: 3 + 7 + 19 = 29 3+7+19=29 3+7+19=29。
输入格式
第一行两个空格隔开的整数 n , k n,k n,k( 1 ≤ n ≤ 20 1 \le n \le 20 1≤n≤20, k < n k<n k<n)。
第二行 n n n 个整数,分别为 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn( 1 ≤ x i ≤ 5 × 1 0 6 1 \le x_i \le 5\times 10^6 1≤xi≤5×106)。
输出格式
输出一个整数,表示种类数。
输入输出样例 #1
输入 #1
4 3
3 7 12 19
输出 #1
1
说明/提示
【题目来源】
NOIP 2002 普及组第二题
d f s dfs dfs 选够数后检查和是否是素数
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e8 + 10;
int ans = 0;
int b[22];
int a[22];
int n, k;
int sum = 0;
stack<int>s;
bool check(int x) {
for (int i = 2; i * i < x; i++) {
if (x % i == 0)return false;
}
return true;
}
void dfs(int num, int x) {
if (num == k) {
if (check(sum))ans++;
return;
}
for (int i = x + 1; i <= n; i++) {
b[i] = 1;
sum += a[i];
dfs(num + 1, i);
b[i] = 0;
sum -= a[i];
}
}
int main() {
cin >> n >> k;
for (int i = 1; i <= n; i++)cin >> a[i];
dfs(0, 0);
cout << ans;
return 0;
}
P2036 [COCI 2008/2009 #2] PERKET
题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n n n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s s s 和苦度 b b b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。
输入格式
第一行一个整数 n n n,表示可供选用的食材种类数。
接下来 n n n 行,每行 2 2 2 个整数 s i s_i si 和 b i b_i bi,表示第 i i i 种食材的酸度和苦度。
输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
输入输出样例 #1
输入 #1
1
3 10
输出 #1
7
输入输出样例 #2
输入 #2
2
3 8
5 8
输出 #2
1
输入输出样例 #3
输入 #3
4
1 7
2 6
3 8
4 9
输出 #3
1
说明/提示
数据规模与约定
对于 100 % 100\% 100% 的数据,有 1 ≤ n ≤ 10 1 \leq n \leq 10 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1 × 1 0 9 1 \times 10^9 1×109,酸度和苦度不同时为 1 1 1 和 0 0 0。
d f s dfs dfs 数很大我开的 l o n g long long l o n g long long
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n;
struct food {
ll si, bi;
}f[10];
ll abs1(ll a) {
return a > 0 ? a : -a;
}
ll min(ll a, ll b) {
return a < b ? a : b;
}
ll s = 1;
ll b = 0;
ll minn;
void dfs(int x){
for (int i = x + 1; i <= n; i++) {
s *= f[i].si;
b += f[i].bi;
minn = min(abs(s - b), minn);
dfs(i);
s /= f[i].si;
b -= f[i].bi;
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++)cin >> f[i].si >> f[i].bi;
minn = abs1(f[1].si - f[1].bi);
dfs(0);
cout << minn;
return 0;
}
P1605 迷宫
题目描述
给定一个 N × M N \times M N×M 方格的迷宫,迷宫里有 T T T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N , M , T N,M,T N,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 S X , S Y , F X , F Y SX,SY,FX,FY SX,SY,FX,FY, S X , S Y SX,SY SX,SY 代表起点坐标, F X , F Y FX,FY FX,FY 代表终点坐标。
接下来 T T T 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
输入输出样例 #1
输入 #1
2 2 1
1 1 2 2
1 2
输出 #1
1
说明/提示
对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 5 1 \le N,M \le 5 1≤N,M≤5, 1 ≤ T ≤ 10 1 \le T \le 10 1≤T≤10, 1 ≤ S X , F X ≤ n 1 \le SX,FX \le n 1≤SX,FX≤n, 1 ≤ S Y , F Y ≤ m 1 \le SY,FY \le m 1≤SY,FY≤m。
d f s dfs dfs
#include<bits/stdc++.h>
using namespace std;
int n, m, t;
int sx, sy, fx, fy;
int ans;
int xx[4] = { -1,0,1,0 };
int yy[4] = { 0,-1,0,1 };
int a[7][7];
int b[7][7];
void dfs(int x1, int y1) {
if (x1 == fx && y1 == fy) {
ans++;
return;
}
for (int i = 0; i < 4; i++) {
int x2 = x1 + xx[i];
int y2 = y1 + yy[i];
if (x2 >= 1 && x2 <= n && y2 >= 1 && y2 <= m && !a[x2][y2] && !b[x2][y2]) {
b[x2][y2] = 1;
dfs(x2, y2);
b[x2][y2] = 0;
}
}
}
int main() {
cin >> n >> m >> t;
cin >> sx >> sy >> fx >> fy;
for (int i = 0; i < t; i++) {
int p, q;
cin >> p >> q;
a[p][q] = 1;
}
b[sx][sy] = 1;
dfs(sx, sy);
cout << ans;
return 0;
}