回溯法
当把问分成若干个不走并递归求解时,如果当前步骤没有合法选择,则函数将返回上一级递归调用,这种现在称为回溯
八皇后问题
史上最经典的问题了,感觉哪里都能看到它,人工智能,算法?hhh好像也就这些,但是哪里都有它hhh
输出:
0 1
1 1
2 0
3 0
4 2
5 10
6 4
7 40
8 92
9 352
10 724
11 2680
12 14152
13 70860
14 288980
15 1308958
16 4310906
code:
#include <stdio.h>
const int MAXN=20;
int vis[MAXN][MAXN];
int C[MAXN];
int tot=0;
void search(int cur,int m){
int i,j;
if(cur==m) tot++;
else for(i=0;i<m;i++){
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+m]){
C[cur]=i;
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+m]=1;
search(cur+1,m);
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+m]=0;
}
}
}
int main() {
int n;
for(n=0;n<=16;n++){
search(0,n);
printf("%d %d\n",n,tot);
tot=0;
}
return 0;
}
素数环
题目:输入整数n,把整数1,2,3…,n组成一个环,使得相邻的整数之和为素数。输出时从整数n开始逆时针输出排列。同一个环应该恰好输出一次。
输入:
6
输出:
1 4 3 2 5 6
1 6 5 2 3 4
首先回顾素数的判断,将每个数循环一遍判断是否为素数,如果为素数就在标记数组isp对应的位置输出1,如果不是则为0。
接着是打印过程,以cur==n && isp[A[0]+A[n-1]]为界限,表示你已经组成了哪个刚刚好的循环了,输出。
接着就是回溯了,创建循环,每个数遍历一遍,如果没有访问过而且满足和前一个数相加为素数,就标记。然后回溯下一个数组的元素,也就是cur+1.
code:
#include <cstdio>
#include<cstring>
#include<iostream>
#include<math.h>
using namespace std;
const int MAXN=10010;
int isp[MAXN];
int A[MAXN];
int vis[MAXN];
int n;
int is_prime(int x){
if(n<=1) return 0;
int k=floor(sqrt(x)+0.5);
for(int i=2;i<=k;i++)
if(x%i==0) return 0;
return 1;
}
void dfs(int cur){
if(cur==n && isp[A[0]+A[n-1]]){
for(int i=0;i<n;i++) printf("%d ",A[i]);
printf("\n");
}
else for(int i=2;i<=n;i++){
if(!vis[i] && isp[i+A[cur-1]]){
A[cur]=i;
vis[i]=1;
dfs(cur+1);
vis[i]=0;
}
}
}
int main() {
int flag=0;
while(scanf("%d",&n)!=EOF && n>0){
if(flag>0) printf("\n");
printf("%d\n",++flag);
for(int i=2;i<=n*2;i++) isp[i]=is_prime(i);
memset(vis,0,sizeof(vis));
A[0]=1;
dfs(1);
}
return 0;
}
困难的串
题目:如果一个字符串包含两个相邻的重复子串,则称他为“容易的串”,其他串为“困难的串”。输入正整数n和L,输出由前L个字符组成的,字典序第k小的困难的串。
输入:
7 3
30 3
输出:
ABACABA
ABACABCACBABCABACABCACBACABACB
code:
#include <stdio.h>
#include<string.h>
int n,L;
const int MAXN=1001;
int S[MAXN];
int dfs(int cur){
if(cur==n){
for(int i=0;i<cur;i++)
printf("%c",'A'+S[i]);
printf("\n");
return 0;
}
for(int i=0;i<L;i++){
S[cur]=i;
int ok=1;
for(int j=1;j*2<=cur+1;j++){
int equal=1;
for(int k=0;k<j;k++){
if(S[cur-k]!=S[cur-k-j]){
equal=0;break;
}
}
if(equal) {ok=0;break;}
}
if(ok) if(!dfs(cur+1)) return 0;
}
return 1;
}
int main() {
while(scanf("%d %d",&n,&L)!=EOF){
dfs(0);
memset(S,0,sizeof(S));
}
return 0;
}