【Wikioi】1008-选数
来源:互联网 发布:java什么叫反射 编辑:程序博客网 时间:2024/05/22 00:46
已知 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;}
0 0
- 【Wikioi】1008-选数
- wikioi 1008 选数 普及组 2002
- wikioi 1045 回文数
- wikioi 丑数
- WIKIOI-1264 芳香数
- wikioi 数的划分
- WikiOI 2924 数独挑战
- wikioi p1011 数的计算
- wikioi p1039 数的划分
- wikioi-1039-数的划分
- 【wikioi】1011 数的计算
- wikioi 1037 取数游戏
- wikioi 1039 数的划分
- wikioi 1043 方格取数
- [Wikioi 1037]取数游戏
- wikioi数的计算c++
- wikioi方格取数c
- wikioi 1011 数的计算
- sql小技巧
- easyui框架按钮的类型
- 做网站前需要考虑的几个问题
- java格式化输出 printf 例子
- 【线性表】顺序存储结构之:顺序表
- 【Wikioi】1008-选数
- LeetCode: Generate Parentheses [021]
- configure: error: could not find working GL library
- 自拉ADSL网线搭建网站服务器,解决动态IP、无公网IP、80端口被封、HTTP被屏蔽的方法
- Linux-2.6.25内核帧缓冲设备驱动分析
- Android手电筒,闪光灯
- 包与访问修饰符
- SQL join中on与where的区别介绍
- Linux /dev目录详解