共计 4081 个字符,预计需要花费 11 分钟才能阅读完成。
N 皇后问题
在 N * N 的方格棋盘搁置了 N 个皇后,使得它们不互相攻打(即任意 2 个皇后不容许处在同一排,同一列,也不容许处在与棋盘边框成 45 角的斜线上。
你的工作是,对于给定的 N,求出有多少种非法的搁置办法。
Input
共有若干行,每行一个正整数 N≤10,示意棋盘和皇后的数量;如果 N =0,示意完结。
Output
共有若干行,每行一个正整数,示意对应输出行的皇后的不同搁置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
这道题我老是 Time Limit, 有空还要优化一下,有大佬请帮我看下
//// 求 N * N 的格子摆放皇后的摆法(求有几种摆法而不是能够放多少个皇后)(递归)//#include<iostream>
//#include<algorithm>
//#include<string>
//#include<string.h>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<set>
//using namespace std;
//int n,cnt;
//int vis[3][50];//vis[3]第一个中括号来辨别不同拜访类型三种类型,0(vis[0][])示意判断 同一列 的格子是否被拜访过
////1(vis[1][])示意判断 右斜对角 的格子是否被拜访过,2(vis[2][])示意判断 左斜对角 的格子是否被拜访过
////#include<bits/stdc++.h>// 万能头文件
//void dfs(int row){// 把 queen 所在的行传入 dfs
// if(row == n + 1){// 递归进口条件、边界(如果超过第 n 行了)
// cnt++;// 递归终止回溯一次,记录一次个数
// return ;
// }
// for(int i = 1; i <= n; i++){// if(vis[0][i] == 0 && vis[1][n + row - i] == 0 && vis[2][i + row] == 0){// vis[0][i] = vis[1][n + row - i] = vis[2][i + row] = 1;
// dfs(row + 1);
// vis[0][i] = vis[1][n + row - i] = vis[2][i + row] = 0;// 在深搜遍历的时候每一个格子的同行同列、左右对角都被拜访标记了
// // 然而回溯的时候只是找到了一个适合的格子,(除该以后格子外)其余格子要从新复原为未拜访
// }
// }
//}
//int main(){// memset(vis,0,sizeof(vis));
// while(cin >> n,n != 0){
//// int cnt = 0;// 记录皇后搁置的数量, 应定义为全局变量
//// int n;// 因为深搜外面也用到该变量,应定义为全局变量
// cnt = 0;
// dfs(1);
// cout << cnt << endl;
// }
// return 0;
//}
//
另一种办法,引入 check 函数,但实质还是递归
//// 求 N * N 的格子摆放皇后的摆法(求有几种摆法而不是能够放多少个皇后)(递归)//#include<iostream>
//#include<algorithm>
//#include<string>
//#include<string.h>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<set>
//using namespace std;
//int n,cnt;
//int a[10];//a[i]示意第 i 行上的 queen 放于 a[i]列上,如 a[3] = 7 示意第 3 行第 7 列的格子有 queen
////#include<bits/stdc++.h>// 万能头文件
//// 字符翻转
//bool check(int x, int y){// 传入行值和列值(相当于 a[i]), 看是否和 queen 所在的值绝对应或同行同列斜对角
// for(int i = 1; i <= x; i++){// 只用看在某行格子放 queen 之后,其前 x 行所对应的格子满足不满足条件, 一个一个格子枚举比照
// if(a[i] == y){//check 同列是否满足,应为是按行放,每行只放一个,同行无需验证
// return false;// 判断 a[i]的值是否等于 1,2,3,4,5,6 等 dfs 外面 for(的 i 值),排除同列的
// // 不满足这个 if 及上面两个 if 就算找到了,完结 check 进行赋值操作 a[row] = i
// }
// if(i + a[i] == x + y){//check / 对角线是否满足
// return false;
// }
// if(i - a[i] == x - y){//check \ 对角线是否满足
// return false;
// }
// }
// return true;// 留神要放在 for 循环里面,for 全副执行之后没问题再返回 true. 都没有问题,返回 queen 能够放在这个格子
//}
//void dfs(int row){// 把 queen 所在的行传入 dfs
// if(row == n + 1){// 递归进口条件、边界(如果超过第 n 行了)
// cnt++;// 递归终止回溯一次,记录一次个数
// return ;
// }
// for(int i = 1; i <= n; i++){// if(check(row,i)){//check 一下第 row 行的皇后能不能放在第 row 行第 i 列上
// a[row] = i; // 能够放就给第 row 行的第 i 个 (列) 格子放上
// dfs(row + 1);
// a[row] = 0;// 进行完每次回溯把相应的第 row 行还原置零,从新开始,即没次 dfs 完后 row 行的皇后地位回到第一列开始往后找
// }
// }
//}
//int main(){// while(cin >> n,n != 0){
//// int cnt = 0;// 记录皇后搁置的数量, 应定义为全局变量
//// int n;// 因为深搜外面也用到该变量,应定义为全局变量
// cnt = 0;
// dfs(1);
// cout << cnt << endl;
// }
// return 0;
//}
//
Prime Ring Problem
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, …, n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.
Input
n (0 < n < 20).
Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.
Sample Input
6
8
Sample Output
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4
Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<set>
using namespace std;
/*
素数环指的是将从 1 到 n 这 n 个整数围成一个圆环,若其中任意 2 个相邻的数字相加,后果均为素数
*/
int n,a[30],vis[30];// n 是数字的个数,a[i]是需遍历的数组,vis[]是标记数组是否被拜访过
bool Prime(int yy)// 判断素数
{for(int i=2; i<=sqrt(yy); i++)
{if(yy%i==0)
{return false;}
}
return true;
}
void dfs(int t){// 此处的 t 只是传参,跟 main 函数外面的 t 没有关系
if(t == n && Prime(a[t - 1] + a[0])){// t 是从 0 开始,当 t = n 时阐明 a[0,...t - 1]都填入了合规的数
for(int i = 0; i < t - 1; i++){//num 从 0 开始
printf("%d",a[i]);
}
printf("%d\n",a[t - 1]);//a[num - 1]就是传入的 num 下标对应的值
}else{// 尝试能够填入 a[i]的每一种可能性(穷举)
for(int i = 2; i <= n; i++){// i 代表所有的可能性
if(vis[i] == 0 && Prime(i + a[t - 1])){// i 没有应用过,还没连贯在环上并且 i 和他前一位的和是素数
// 此处 i = 2 是因为,dfs(1)从 1 开始并且 1 = a[1-1], 所以从 2 开始枚举(看 2 与 1 之和是否素数以及)
vis[i] = 1;// 用过的数标记 1
a[t] = i; // 满足条件给所求数组的第一个地位 a[1]赋值
dfs(t + 1);// 在 a[1] = i 根底上 对 i 之后的每个数持续递归判断
vis[i] = 0;// 进行完每次通过 n 此 dfs 后, 该回溯的时候把相应的 i 还原置零,不便下一个传入的 t 持续枚举
}
}
}
}
int main(){
int t = 1;// 定义一个用来记录 case 后序号的变动
a[0] = 1;
while(cin >> n){memset(vis,0,sizeof(vis));// 标记数组 vis 初始化为 0
printf("Case %d:\n",t++);// 输入一下头部格局,case 前面的数字自增
dfs(1);// 传入 1 开始进行深搜
printf("\n");
}
}