BFS DFS ----习题
题目1
答案1
#include <bits/stdc++.h>using namespace std;const int N = 210;
int n,k;
int arr[N];
int res = 0;void dfs(int x,int start,int nowsum)
{if (nowsum > n) return ;if(x>k){if(nowsum == n) res++;return ;}for(int i = start;nowsum+i*(k-x+1)<=n;i++){arr[x]=i;dfs(x+1,i,nowsum+i);arr[x]=0;}
}int main()
{cin >> n >> k;dfs(1,1,0);cout << res;return 0;}
这题比较烦的方面在于如何剪枝缩短时间
关键在于在DFS函数中加入nowsum的参数,做到边和边判断,遇到了nowsum>n的情况就可以剪枝了,避免了x>k之后再循环算和。最最核心的是nowsum+i*(k-x+1)<=n,这条减少了继续深搜的分支。
题目2
答案2
#include <bits/stdc++.h>
#define x first
#define y secondusing namespace std;
typedef pair<int,int> PII;const int N = 510;int n, m, a, b;
int dist[N][N];
PII q[N * N];
int hh = 0, tt = -1;int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};void bfs() {while (hh <= tt) {auto t = q[hh++];for (int i = 0; i < 4; i++) { int a = t.x + dx[i], b = t.y + dy[i];if (a < 1 || a > n || b < 1 || b > m) continue;if (dist[a][b] != -1) continue; dist[a][b] = dist[t.x][t.y] + 1;q[++tt] = {a, b};}}
}int main() {cin >> n >> m >> a >> b;memset(dist, -1, sizeof dist);while (a--) {int x1, y1;cin >> x1 >> y1;q[++tt] = {x1, y1};dist[x1][y1] = 0;} bfs();while (b--) {int x1, y1;cin >> x1 >> y1;cout << dist[x1][y1] << endl;}return 0;
}
自己写错的原因是
for (int i = 0; i < 4; i++) {
int a = t.x + dx[i], b = t.y + dy[i];}
i应该是从0开始,而不是1。
别人的答案:
题目3
答案3
#include <bits/stdc++.h>#define x first
#define y secondusing namespace std;const int N = 410;
typedef pair<int, int> PII;int n,m;
int dist[N][N];
PII q[N*N];
int hh=0,tt=0;int dx[] = {1,1,2,2,-1,-1,-2,-2};
int dy[] = {-2,2,-1,1,-2,2,-1,1};void bfs(int x,int y)
{memset(dist,-1,sizeof dist);q[0]={x,y};dist[x][y]=0;while(hh<=tt){auto t = q[hh++];for(int i = 0;i<8;i++){int a = t.x+dx[i],b=t.y+dy[i];if (a < 1 || b < 1 || a > n || b > m) continue; // 越界检查if (dist[a][b] >= 0) continue; // 已经访问过的点跳过dist[a][b] = dist[t.x][t.y]+1;q[++tt] = {a,b};}}}int main()
{int x1,y1;cin >> n >> m >> x1 >> y1;bfs(x1,y1);for(int i = 1;i<=n;i++){for(int j = 1;j<=m;j++){printf("%-5d",dist[i][j]);}cout << endl;}
}