简单回溯法
全排列问题
题目描述
请给出N的全排列
输入
输入一个整数N。
N有多个。
输出
输出N的全排列。
样例输入
2
3
样例输出
1 2
2 1
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
#include <iostream>
using namespace std;
int a[20] = {0}, n;
int test(int i, int k) {
int t = 0;
for (int j = 1; j <= i-1; j++) {
if (a[j] == k) {
t = 1;
break;
}
}
if (!t) return 1;
return 0;
}
void try1(int i) {
if (i == n+1) {
for (int j = 1; j < n; j++) {
cout << a[j] << " ";
}
cout << a[n] <<"\n";
} else {
for (int k = 1; k <= n; k++) {
if (test(i, k) == 1) {
a[i] = k;
try1(i+1);
}
}
}
}
int main() {
while (cin >> n) {
try1(1);
cout << "\n";
}
return 0;
}
n皇后问题
题目描述
在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
输入
整数n.n小于等于10
输出
输出满足n皇后问题的解的个数
样例输入
4
8
样例输出
2
92
#include <iostream>
using namespace std;
int vis[2][1009] = {0};
int tot = 0;
void search(int cur);
int n; // 皇后数目
int main() {
while (cin >> n) {
tot = 0;
search(0);
cout << tot << endl;
}
return 0;
}
void search(int cur) {
if (cur == n) tot++;
else {
for (int i = 0; i < n; i++) {
if (!vis[0][i] && !vis[1][cur+i] && !vis[2][cur-i+100]) {
vis[0][i] = vis[1][cur+i] = vis[2][cur-i+100] = 1;
search(cur+1);
vis[0][i] = vis[1][cur+i] = vis[2][cur-i+100] = 0;
}
}
}
}
问题 C: 马踏棋盘问题
题目描述
在N*M的棋盘中,马只能走日字,马从(x,y)处出发,把棋盘的每一格都走一次且只走一次,所有路径条数。
输入
输入两个整数M,N,
以及起点位置,x,y(>=0且<=20);
输出
输出路径条数
样例输入
2 3
0 0
样例输出
0
#include <iostream>
#include <queue>
using namespace std;
typedef struct Node {
int x;
int y;
int v;
};
Node path[109][109];
int m, n; // 棋盘范围
int cnt = 0; // 统计路线数量
void test() {
bool judge = true;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!path[i][j].v) { // 发现未走过的点, 则不是路径
judge = false;
}
}
}
if(judge)cnt++; // 全部走过, 路径数 + 1
}
int fx[] = {1, 2, 2, 1, -1, -2, -2, -1};
int fy[] = {2, 1, -1, -2, -2, -1, 1, 2};
queue<Node> myQue;
void bfs(int i, int j) {
myQue.push(path[i][j]);
path[i][j].v = 1;
while (!myQue.empty()) {
Node front = myQue.front();
for (int i = 0; i < 8; i++) {
if (front.x+fx[i] >= 0 && front.x+fx[i] < m &&
front.y+fy[i] >= 0 && front.y+fy[i] < n ) // 判断是否越界
{
if (!path[front.x+fx[i]][front.y+fy[i]].v) { // 未走过的点
myQue.push(path[front.x+fx[i]][front.y+fy[i]]);
path[front.x+fx[i]][front.y+fy[i]].v = 1;
}
}
}
test(); // 判断是否走满棋盘
myQue.pop();
}
}
void Clear(int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
path[i][j].x = i;
path[i][j].y = j;
path[i][j].v = 0;
}
}
cnt = 0; // 计数器置0
}
int main() {
int x, y;
while (cin >> m >> n >> x >> y) {
Clear(m, n); // 初始化
bfs(x, y);
cout << cnt << endl;
}
return 0;
}
素数环问题
题目描述
把1~N(N<=20)个数摆成一个环,要求相邻两个数的和是素数。
环的第一个位置应该放1。
输出合法环的个数。
输入
输入一个整数
输出
输出环的个数
样例输入
6
样例输出
2
#include <iostream>
using namespace std;
int is_prime[49] = {0, 0, 2, 3, 0, 5, 0, 7, 0, 0, 0, // 第一位为0
11, 0, 13, 0, 0, 0, 17, 0, 19, 0,
0, 0, 23, 0, 0, 0, 0, 0, 29, 0,
31, 0, 0, 0, 0, 0, 37, 0, 0, 0};
int n, v[49] = {1, 1, 0}, s[49] = {1, 0}, cnt = 0; // v数组0和1由题目默认不能访问, s数组由题目第一位放1
void dfs(int cur, int n) {
if (cur == n && is_prime[s[0] + s[n - 1]]) {
cnt++;
} else {
for (int i = 2; i <= n; i++) {
if (!v[i] && is_prime[i + s[cur - 1]]) {
s[cur] = i;
v[i] = 1;
dfs(cur + 1, n);
v[i] = 0;
}
}
}
}
int main() {
int n;
while (cin >> n) {
dfs(1, n);
cout << cnt << endl;
}
return 0;
}
迷宫 回溯
题目描述
从S走到D,恰好走T步,能不能走到?走到输出YES,走不到输出NO,X为墙,不能走。
输入
输入三个整数,M,N,T,表示M行N列的迷宫,T为时间,单位分钟。M,N,T全为零是结束输入。
然后是迷宫,X为墙, .可以走。
输出
输出YES或NO
样例输入
4 4 5
S.X.
..X.
..XD
….
3 4 5
S.X.
..X.
…D
0 0 0
样例输出
NO
YES
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
typedef struct Node {
int x;
int y;
int v;
char c;
};
Node path[59][59];
int xx, yy;
void bfs(int x, int y) {
queue<Node> myQue;
path[x][y].v = 1;
myQue.push(path[x][y]);
while (!myQue.empty()) {
Node front = myQue.front();
// 判断四个方向是否能够入队
if (!path[front.x+1][front.y].v) {
path[front.x+1][front.y].v = front.v + 1;
myQue.push(path[front.x+1][front.y]);
}
if (!path[front.x][front.y+1].v) {
path[front.x][front.y+1].v = front.v + 1;
myQue.push(path[front.x][front.y+1]);
}
if (!path[front.x-1][front.y].v) {
path[front.x-1][front.y].v = front.v + 1;
myQue.push(path[front.x-1][front.y]);
}
if (!path[front.x][front.y-1].v) {
path[front.x][front.y-1].v = front.v + 1;
myQue.push(path[front.x][front.y-1]);
}
if (front.c == 'D') { // 如果该位置为D, 则记录位置并退出
xx = front.x;
yy = front.y;
return;
}
myQue.pop();
}
}
void Clear(int m, int n) {
for (int i = 0; i <= m + 5; i++)
for (int j = 0; j <= n + 5; j++) {
path[i][j].v = 1;
path[i][j].x = i;
path[i][j].y = j;
path[i][j].c = ' ';
}
}
int main() {
int m, n, t;
while (cin >> m >> n >> t) {
if (m == 0 || n == 0 || t == 0)break;
Clear(m, n); // 重置数组
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cin >> path[i][j].c;
if (path[i][j].c != 'X') { // 0可走, 1不可走
path[i][j].v = 0;
}
}
getchar();
}
bfs(1, 1);
printf("%s\n", (path[xx][yy].v-1 <= t) ? "YES" : "NO"); // 需要减去起点1
}
return 0;
}
迷宫问题
题目描述
小明得到一张迷宫地图,他想从(1,1)出发,找一条最短的到(8,8)的路径。
输入
现输入整数N,表示数据包含N行N列个数。然后输入四个整数,分别表示起点和终点的行列值。
然后是N行N列个数,0表示可以通过,1表示不能通过
输出
最短要走几步
样例输入
8
1 1 8 8
0 0 0 0 0 0 0 0
0 1 1 1 1 0 1 0
0 0 0 0 1 0 1 0
0 1 0 0 0 0 1 0
0 1 0 1 1 0 1 0
0 1 0 0 0 0 1 1
0 1 0 0 1 0 0 0
0 1 1 1 1 1 1 0
样例输出
14
#include <iostream>
#include <queue>
using namespace std;
typedef struct Node {
int x;
int y;
int v;
};
Node path[59][59];
void bfs(int x, int y) {
queue<Node> myQue;
path[x][y].v = 1;
myQue.push(path[x][y]);
while (!myQue.empty()) {
Node front = myQue.front();
if (!path[front.x+1][front.y].v) {
path[front.x+1][front.y].v = front.v + 1;
myQue.push(path[front.x+1][front.y]);
}
if (!path[front.x][front.y+1].v) {
path[front.x][front.y+1].v = front.v + 1;
myQue.push(path[front.x][front.y+1]);
}
myQue.pop();
}
}
void Clear(int n) {
for (int i = 0; i <= n + 5; i++)
for (int j = 0; j <= n + 5; j++) {
path[i][j].v = 1;
path[i][j].x = i;
path[i][j].y = j;
}
}
int main() {
int n, x1, y1, x2, y2;
while (cin >> n) {
Clear(n); // 重置数组
cin >> x1 >> y1 >> x2 >> y2;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
cin >> path[i][j].v;
}
bfs(x1, y1);
for (int ii = 1; ii <= n; ii++){
for (int jj = 1; jj <= n; jj++) {
cout << path[ii][jj].v << " ";
}
cout << endl;
}
cout << path[x2][y2].v - 1 << endl; // 起点不算, 需减掉
}
return 0;
}