(回溯Uva524)素數環
阿新 • • 發佈:2019-01-23
題目
輸入正整數,把整數1,2,3,···,n組成一個環,使得相鄰兩個整數之和均為素數。輸出時從整數1開始逆時針排列。同一個環應恰好輸出一次。n<=16
樣例輸入
6
樣例輸出
1 4 3 2 5 6
1 6 5 2 3 4
分析與解答
用一個數組a存答案,由於是從1開始,a[0]=1,
void DFS ( Vertex V )
{
visited[ V ] = true;
if(…) return;
for ( V 的每個鄰接點 W )
if ( !visited[ W ] )
DFS( W );
}
在這個題中,深搜需要的終止條件,l==n&&isp[A[0]+A[n-1]],l是位置,如果已確定了n個位置,說明此時終止,並且如果第一個a[0]等於a[n-1]說明此時終止,終止的話,從0到n-1輸出即可
如果不滿足終止條件,我們就找新的數填到位置l,然後遞迴找下一個位置需要填的數,如何知道該位置填什麼數?我們知道第一個數是1,那這個位置的數我們假設是2到n中任一個,迴圈,如果滿足這個數不曾出現而且和上一個位置的數之和為素數,那我們就把這個位置填上這個數,把標記陣列標記用來表明這個數已經被用過,並且遞迴呼叫找下個位置,我們遞迴完了還要清除標記陣列的標記,就像是找到了一個可能情況,就不斷地回溯一樣,這樣的話最終會找出所有情況
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int is_prime(int x) {
for(int i = 2; i*i <= x; i++)
if(x % i == 0) return 0;
return 1;
}
int n, A[50], isp[50], vis[50];
void dfs(int l){
if(l==n&&isp[A[0]+A[n-1 ]]){
for(int i=0;i<n;++i)
if(i==0) printf("%d",A[i]);
else printf(" %d",A[i]);
printf("\n");
}
else{
for(int i=2;i<=n;++i)
if(!vis[i]&&isp[i+A[l-1]]){
A[l]=i;
vis[i]=1;
dfs(l+1);
vis[i]=0;
}
}
}
int main() {
int kase = 0;
for(int i = 2; i <= 20*2; i++) isp[i] = is_prime(i);
while(scanf("%d", &n) == 1 && n > 0) {
printf("Case %d:\n", ++kase);
memset(vis, 0, sizeof(vis));
A[0] = 1;
dfs(1);
printf("\n");
}
return 0;
}