已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34。
现在,要求你计算出和为素数共有多少种。
3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34。
现在,要求你计算出和为素数共有多少种。
典型的DFS:
第一种方法时间复杂度高,n!,而且不好理解,是按照如下的解答树走的:
r
1 2 3 11
2 3 11 , 3 11, 11
递归时如果不满足if条件,则会返回到上一层,注意这里的line是局部变量,每次递归都会复制一次,return到上一层,自动回到那时候的状态,不用还原标记,
这也就是为什么有时候局部变量需要还原,而有时候不用。在这个for循环里面,line没有改变,不用pop。(有些程序push在for里面,比如Subsets,那么就需要还原)。
在dfs()中,ans1为全局变量,对整体有影响,所以必须要还原标记;
【基本上如果是全局的,那肯定要还原;局部要看情况(每一组push和dfs写一起的基本要pop下,如果在for外面,那么就可能不用)】
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include <vector>
using namespace std;
int n,k;
int w[30];
int res=0;
int ans1=0;
vector<int> each_res;
bool isPrime(int x)
{
if(x==1)
return false;
for(int i=2; i<=sqrt(x); i++)
{
if(x%i==0)
return false;
}
return true;
}
void dfs(int x,int m)
{
ans1+=w[x];
if(m==k)
{
if(isPrime(ans1))
{
cout<<"ans :"<<ans1<<endl;
res++;
}
}
else for(int j=x+1; j<=n; j++)
dfs(j,m+1);
ans1-=w[x];//必须清除标记
}
void dfs_eachres(int first, int ans,int m)
{
ans+=w[first];
each_res.push_back(w[first]);
if(m==k)
{
if(isPrime(ans))
{
cout<<"ans :"<<ans<<endl;
res++;
for(int i=0; i<k; i++)
cout<<each_res[i]<<" ";
cout<<endl;
}
}
else for(int i=first+1; i<=n; i++)
{
dfs_eachres(i,ans, m+1);
}
each_res.pop_back();
//ans-=w[first];
}
int main()
{
n=4,k=2;
w[1]=1,w[2]=2,w[3]=3,w[4]=11;
//for(int i=1; i<=n; i++)
// dfs(i,0,1);
//dfs2(0, 0);//重复 11 12 21
for(int i=1; i<=n; i++)
dfs_eachres(i, 0, 1);
// dfs(i,1);
cout<<res;
}
这里的dfs写法比较复杂,时间复杂度为n!,其实有更好的写法,就是对第i为取不取的问题,时间复杂度为2^n。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include <vector>
using namespace std;
int n,k;
int w[30];
int res=0;
bool isPrime(int x)
{
if(x==1)
return false;
for(int i=2; i<=sqrt(x); i++)
{
if(x%i==0)
return false;
}
return true;
}
void dfs(int s,int ans,int m,vector<int> line) {
if(s>n+1){
return;
}
if(m == k){
if(isPrime(ans)){
cout<<"ans :"<<ans<<endl;
res++;
for(int i=0; i<k; i++)
cout<<line[i]<<" ";
cout<<endl;
}
return;
}
line.push_back(w[s]);
dfs(s+1,ans+w[s],m+1,line);
line.pop_back();
dfs(s+1,ans,m,line);
}
int main()
{
n=4,k=2;
w[1]=1,w[2]=2,w[3]=3,w[4]=11;
vector<int> line;
dfs(1, 0, 0, line);
cout<<"res: "<<res;
}