搜索 HDU-1016 Prime Ring Problem
题目链接:杭电1016
题目大意:输入一个n 使从1到n的整数互相连接形成一个环 要求环节点的数字与左右两边的数字和均为素数 按字典序输出
解题思路:DFS 因为所求为一个环 又要字典序排序 所以第一个数字一定为1 同一级递归确定的数字为同一个位置放的数字 如果递归到n+1位则将n位与1位数字之和相加判断输出 若不是n+1位 则从2开始遍历 数字没有用过就进行一次判断 若遍历到的数字与前一位的数字之和为素数 则进行下一次的判断 函数返回后记得将刚才用的数字释放为未使用
代码块:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int nums[21] = { 0 };//储存当前数字
bool used[21] = { 0 };//是否被用过
bool isPrime[39] = { 0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0 };//判断是否为素数
int n;
void dfs(int p);
int main() {
int index=0;
while (cin >> n) {
index++;
printf("Case %d:\n", index);
nums[1] = 1;//以数字1作为圈的起点
used[1] = true;//数字1已经用过
dfs(2);
memset(nums, 0, sizeof(nums));
memset(used, false, sizeof(used));
cout << endl;
}
return 0;
}
void dfs(int p) {
//如果已经是最后一位则进行判断是不是和第一位加起来为素数 是输出 不是返回
if (p == n + 1) {
if (!isPrime[nums[p - 1] + 1]) return;
else {
cout << "1";
for (int i = 2; i <= n; i++) {
cout << " " << nums[i];
}
cout << endl;
return;
}
}
//没到最后一位
else {
for(int i=2;i<=n;i++){
if (used[i]) continue;//如果当前的i值有被用过则跳过
//前一位加当前判断的数字之和是素数就记录数字
if (isPrime[i + nums[p-1]]) {
nums[p] = i;
used[i] = true;
dfs(p + 1);
used[i] = false;//如果函数返回后执行下一步要将刚才执行的那一个数字释放,即没有被用过
}
}
}
}
二刷代码块
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
bool arrA[] = {0,1,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0};
bool isU[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int res[21];
int n = 0;
int sum = 1;
void dfs(int x);
int main(){
int i = 1;
while(cin>>n){
cout<<"Case "<<i<<":"<<endl;
res[0] = 1;
dfs(1);
cout<<endl;
i++;
memset(isU,0,sizeof(isU));
sum = 1;
}
return 0;
}
void dfs(int x){
if(sum == n && arrA[res[sum - 1]+1]){
for(int i = 0; i < sum-1; i++){
cout<<res[i]<<" ";
}
cout<< res[sum - 1]<<endl;
}else{
for(int i=2; i<= n; i++){
if(!isU[i] && arrA[res[sum - 1] + i]){
isU[i] = true;
res[sum++] = i;
dfs(i);
isU[i] = false;
sum--;
}
}
}
}