先来上一道回溯经典题目(NOIP2002普及组二 选数):
已知 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+19=29。
Input
键盘输入,格式为:
n , k (1 <= n <= 20,k < n)
x1,x2,…,xn (1 <= xi <= 5000000)
Output
一个整数(满足条件的种数)。
Sample Input 1
4 3 3 7 12 19Sample Output 1
1
这道题感觉和全排列here的思路很像,从n个数中选择k个数,最后对这k个数的总值进行判断是否是质数,如果是质数那么方案数就+1,废话不多说,上代码:
#include<bits/stdc++.h>
using namespace std;
int n,r,ans=0;//ans即方案数
int a[21];//题目说n<20
bool b[21];//同上
bool zs(int x){//质数判断
for(int i=2;i<=sqrt(x);i++)
if(x%i==0) return 0;
return 1;
}
inline void dfs(int k,int js,int y){//回溯
if(k==r){//如果已经选了k个数,并且这k个数的值为质数,那么就让方案数+1
if(zs(js))
ans++;
return ;//返回
}
for(int i=y;i<=n;i++){//从第y个数开始选
dfs(k+1,js+a[i],i+1);//递归
}
return ;//回溯最后都要加一个return负责退出
}
int main(){
cin>>n>>r;//读入
for(int i=1;i<=n;i++)
cin>>a[i];//读入
dfs(0,0,1);//回溯
cout<<ans;//输出
return 0;
}
先说到这,因为笔者是初一,所以没办法花大把时间在写文章,题解上,请见谅。