voiddfs(int x, int y, int s) { if (s > n) return; //可行性剪枝 if (y == n) y = 0, x ++ ; //当列坐标越界,跳转到下一行的首位
if (x == n) //递归边界, 所有行都搜索完 { if (s == n) //皇后数量满足要求 { for (int i = 0; i < n; i ++ ) puts(g[i]); //输出答案 puts(""); } return; //注意这个return一定要在外面,如果在里面某些分支永远到不了边界,最后会tle }
int n; char g[N][N]; //存储方案 int xa, ya, xb, yb; //两点坐标 int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; //方向向量 bool st[N][N]; //标记状态
booldfs(int x, int y) { if (g[x][y] == '#') returnfalse; //如果该点为障碍物,退出 if (x == xb && y == yb) returntrue; //当起点坐标等于终点坐标,返回true
st[x][y] = true; //标记当前点已经走过
for (int i = 0; i < 4; i ++ ) //从x,y点开始遍历四个方向 { int a = x + dx[i], b = y + dy[i]; if (a < 0 || a >= n || b < 0 || b >= n) continue; //新坐标是否在地图内 if (st[a][b]) continue; //新坐标已经走过 if (dfs(a, b)) returntrue; }
returnfalse; }
intmain() { int T; scanf("%d", &T); while (T -- ) { scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%s", g[i]); scanf("%d%d%d%d", &xa, &ya, &xb, &yb);
for (int i = 0; i < 4; i++ ) { int a = x + dx[i], b = y + dy[i]; if (st[a][b]) continue; if (a < 0 || a > n - 1 || b < 0 || b > m - 1) continue; if (g[a][b] == '#') continue; cnt += dfs(a, b); }
return cnt; }
intmain(){ while (cin >> m >> n, n || m) { //输入及停止条件,注意m,n的顺序 其中m是列,n是行 for (int i = 0; i < n; i++ ) cin >> g[i];
int x = 0, y = 0; for (int i = 0; i < n; i++ ) for (int j = 0; j < m; j++ ) if (g[i][j] == '@') x = i, y = j; //找到DFS的起点
int n, m; bool st[N][N]; int ans; int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; //方向数组 int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
voiddfs(int x, int y, int cnt)//cnt记录当前走了几个格子 { if (cnt == n * m) { ans ++ ; return; } st[x][y] = true; //标记
for (int i = 0; i < 8; i ++ ) { int a = x + dx[i], b = y + dy[i]; if (a < 0 || a >= n || b < 0 || b >= m) continue; if (st[a][b]) continue; dfs(a, b, cnt + 1); }
st[x][y] = false; //恢复现场,哪里标记,哪里恢复 }
intmain() { int T; scanf("%d", &T); while (T -- ) { int x, y; scanf("%d%d%d%d", &n, &m, &x, &y);
memset(st, 0, sizeof st); ans = 0; dfs(x, y, 1); //因为递归的时候已经有一个点填进去了,因该赋值为1才对
int n; int p[N]; // 存储每个数 int group[N][N]; // 存储每个组中的数的‘下标’,最多有 N 组,每个数一组 bool st[N]; // 记录每个数是否已经被加入到其他组了 int ans = N; // 最多有 N 组,每个数一组
intgcd(int a, int b)// 欧几里得算法 求最大公约数 { return b ? gcd(b, a % b) : a; }
boolcheck(int group[], int gc, int i)// 判断当前数和组内所有数是否互质 { for (int j = 0; j < gc; j ++ ) if (gcd(p[group[j]], p[i]) > 1) // 如果当前数 p[i] 和组内任意一个数的最大公约数大于 1 则不互质 returnfalse; returntrue; }
// g:第几组,gc:组内元素个数,tc:已经搜索了多少个数了,start:组内从哪个数开始搜索(组合形式搜索防止搜索重复方案) voiddfs(int g, int gc, int tc, int start) { if (g > ans) return; // 剪枝,如果当前方案组数大于 ans,那它一定不是最优,否则比答案小 if (tc == n) ans = g; // 更新最小值
bool flag = true; // 是否需要开新组 for (int i = start; i < n; i ++ ) { // 搜索当前组内可以放哪些数 if (!st[i] && check(group[g], gc, i)) { // 如果当前数没用过 且 和当前组内所有数都互质,则可以将其加入到组内 st[i] = true;
booldfs(int u, int depth)// u 表示当前搜索的深度以及要枚举的位置的下标,depth 表示最大搜索深度 { if (u > depth) returnfalse; // 如果当前搜索深度超过了最大深度还没找到答案,直接返回 false 剪枝 if (path[u - 1] == n) returntrue; // 如果序列最后一个数是 n 了说明找到了一种方案直接返回 true
bool st[N] = {0}; // 标记 和 是否被使用过,相同的和只搜一次,保证这个分支上不搜索重复的节点,st 数组只和当前层有关,不涉及恢复现场 // 从大到小枚举当前位置上可以填的数,且必须是前两两个数的和 for (int i = u - 1; i >= 0; i -- ) for (int j = i; j >= 0; j -- ) { int s = path[i] + path[j]; if (s > n || s <= path[u - 1] || st[s]) continue; // 可行性剪枝 + 排除等效冗余(st[s])
int n, m, k; int g[50]; // 存储所有物品的重量 int weights[N]; // weights存储能凑出来的所有的重量 int cnt = 0; int ans; // 用ans来记录一个全局最大值
// u表示当前枚举到哪个数了, s表示当前的和 voiddfs(int u, int s) { // 如果我们当前已经枚举完第k个数(下标从0开始的)了, 就把当前的s, 加到weights中去 if (u == k) { weights[cnt++] = s; return; }
// 枚举当前不选这个物品 dfs(u + 1, s);
// 选这个物品, 做一个可行性剪枝 if ((LL)s + g[u] <= m) { //计算和的时候转成long long防止溢出 dfs(u + 1, s + g[u]); } }
voiddfs2(int u, int s) { if (u == n) { // 如果已经找完了n个节点, 那么需要二分一下 int l = 0, r = cnt - 1; while (l < r) { int mid = (l + r + 1) >> 1; if (weights[mid] <= m - s) l = mid; else r = mid - 1; } ans = max(ans, weights[l] + s); return; }
// 不选择当前这个物品 dfs2(u + 1, s);
// 选择当前这个物品 if ((LL)s + g[u] <= m) dfs2(u + 1, s + g[u]); }
intmain() { cin >> m >> n; for (int i = 0; i < n; i++) cin >> g[i];
// 优化搜索顺序(从大到小) sort(g, g + n); reverse(g, g + n);
for (int i = 0; i < 4; i ++ ) //往四个方向走 { int x = t.first + dx[i], y = t.second + dy[i]; //在边界内 并且是空地可以走 且之前没有走过 if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1) { d[x][y] = d[t.first][t.second] + 1; //更新 q.push({x, y}); //进队 } } }
return d[n - 1][m - 1]; //返回右下角点的距离 }
intmain() { cin >> n >> m; for (int i = 0; i < n; i ++ ) for (int j = 0; j < m; j ++ ) cin >> g[i][j]; //读入地图信息