回溯法就是是把问题划分为若干个步骤然后递归求解,如果本层没有合适的解,将返回上一层,这个过程中剪了很多不必要的数据,所以效率较高。
生成测试时将所有的都穷举出来,然后测试。
问题:素数环 https://vjudge.net/problem/UVA-524
回溯法:对应n=16,不输出情况下使用43ms
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
using namespace std;
int visited[22]= {0},a[22];
int primelist[22*2]= {0};
int n;
bool isprime(int x)
{
int y;
for(y=2; y<=sqrt(x); y++)
if (x%y==0)
return false;
return true;
}
void dfs(int cur)
{
if(cur==n+1&&primelist[a[1]+a[n]])
{
//for(int i=1;i<n+1;i++)
//cout<<a[i]<<" ";
//cout<<endl;
}
else
{
for(int j=2; j<n+1; j++)
{
if(!visited[j]&&primelist[a[cur-1]+j])
{
visited[j]=1;
a[cur]=j;
dfs(cur+1);
visited[j]=0;
}
}
}
}
int main()
{
for(int i=2; i<22*2-1; i++)
{
if(isprime(i)) primelist[i]=1;
}
a[1]=1;
visited[1]=1;
int p=1;
while(cin>>n)
{
clock_t start=clock(),end;
for(int i=2; i<22; i++) visited[i]=0;
cout<<"Case "<<p++<<":"<<endl;
dfs(2);
end=clock(); //程序结束用时
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
cout<<"Total time:"<<endtime<<endl; //s为单位
}
}
使用生成测试法:n=10,耗时183ms
#include<cstdio>
#include<algorithm>
#include<ctime>
#include<iostream>
#include<cmath>
using namespace std;
int primelist[22*2]= {0};
int n;
bool isprime(int x)
{
int y;
for(y=2; y<=sqrt(x); y++)
if (x%y==0)
return false;
return true;
}
int main()
{
for(int i=2; i<22*2-1; i++)
{
if(isprime(i)) primelist[i]=1;
}
a[1]=1;
visited[1]=1;
int p=1,j;
while(cin>>n)
{
clock_t start=clock(),end;
for(int i=1; i<n+1; i++)
a[i]=i;
a[n+1]=1;
do {
for(j=1; j<n+1; j++)
if(!primelist[a[j]+a[j+1]]) break;
if(j==n+1)
{
for(int i=1; i<n+1; i++)
cout<<a[i]<<" ";
cout<<endl;
}
} while(next_permutation(a+2,a+n+1));
end=clock(); //程序结束用时
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
cout<<"Total time:"<<endtime<<endl; //s为单位
}
}