穷举算法

穷举法也称为枚举法、暴力法,通过搜索所有的解空间得到问题的解。

优点:逻辑简单,编写程序简单、可以解决小规模的问题。

缺点:效率不高。

列一下自己在学习算法的时候总结的有代表性的题目,

问题描述
   如果一个序列满足下面的性质,我们就将它称为摆动序列:
   1. 序列中的所有数都是不大于k的正整数;
   2. 序列中至少有两个数。
   3. 序列中的数两两不相等;
   4. 如果第i – 1个数比第i – 2个数大,则第i个数比第i – 2个数小;如果第i – 1个数比第i – 2个数小,则第i个数比第i – 2个数大。
   比如,当k = 3时,有下面几个这样的序列:
   1 2
   1 3
   2 1
   2 1 3
   2 3
   2 3 1
   3 1
   3 2
   一共有8种,给定k,请求出满足上面要求的序列的个数。

 输入格式
   输入包含了一个整数k。(k<=20)
 输出格式
   输出一个整数,表示满足要求的序列个数。

 样例输入
 3
 样例输出
 8
摆动序列(枚举、深度遍历)
#include<iostream> 
using namespace std; 
int a[25],n,ans; 
int visit[25]; 
int IsCan(int num,int k){     //满足摆动序列条件
    if(k==1 || k==2) return 1; 
    if(a[k-1]>a[k-2] && num<a[k-2]) return 1; 
    if(a[k-1]<a[k-2] && num>a[k-2]) return 1; 
    return 0; 
} 
void dfs(int cur){ //深度优先遍历(cur表示当前填的第几个下标)
    if(cur>n) return ; 
    for(int i=1;i<=n;i++){ 
        if(!visit[i] && IsCan(i,cur)){ 
            visit[i]=1; 
            a[cur]=i; 
            if(cur>=2)     //至少两个数
                ans++;    
            dfs(cur+1);    //继续判断下标 
            visit[i]=0; 
        } 
    }   
} 
int main(){ 
    cin>>n; 
    dfs(1); 
    cout<<ans<<endl; 
} 
题解
2,3,5,7,11,13,....是素数序列。
类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。
上边的数列公差为30,长度为6。
2004年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。
这是数论领域一项惊人的成果!
有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:
长度为10的等差素数列,其公差最小值是多少?
注意:需要提交的是一个整数,不要填写任何多余的内容和说明文字。
等差素数列
#include <iostream>
using namespace std;
typedef long long ll;
//额外提出(n%2),为下面i+=2服务。
bool isprime(ll n){
    if(n <= 1 || (n > 2 && n % 2 == 0)){
        return false;
    }
    for(ll i = 3; i*i <= n; i += 2){
        if(n % i == 0){
            return false;
        }
    }
    return true;
}

int main(){
    for(int d = 2; d < 1000; d ++){
        for(ll n = 2; n < 1000; ++ n){
            if(isprime(n)
            && isprime(n + d)
            && isprime(n + 2*d)
            && isprime(n + 3*d)
            && isprime(n + 4*d)
            && isprime(n + 5*d)
            && isprime(n + 6*d)
            && isprime(n + 7*d)
            && isprime(n + 8*d)
            && isprime(n + 9*d)
            ){
                cout << d << endl;
                break;
            }
        }
    }
    return 0;
}
题解
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。

比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2^符号表示乘方的意思)

对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对4个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法


程序输入为一个正整数N (N<5000000)
要求输出4个非负整数,按从小到大排序,中间用空格分开

再例如,输入:
12
则程序应该输出:
0 2 2 2

再例如,输入:
773535
则程序应该输出:
1 1 267 838

资源约定:
峰值内存消耗 < 256M
CPU消耗  < 3000ms
四平方数
 1 #include <stdio.h>  
 2 #include <math.h>  
 3   
 4 int main()  
 5 {  
 6     int a, b, c, n, flag = 0;  
 7     double maxN, d;  
 8     scanf("%d", &n);  
 9     maxN = sqrt(n);  
10     for(a = 0; a <= maxN; a ++){  
11         for(b = a; b <= maxN; b ++){  
12             for(c = b; c <= maxN; c ++){  
13                 d = sqrt(n - a*a - b*b - c*c);  
14                 if(d == (int)d){  
15                     printf("%d %d %d %d\n", a, b, c, (int)d);  
16                     flag = 1;  
17                     break;  
18                 }  
19             }  
20             if(flag)  
21                 break;  
22         }  
23         if(flag)  
24             break;  
25     }  
26     return 0;  
27 }
题解
 1 问题描述
 2   Torry从小喜爱数学。一天,老师告诉他,像2、357……这样的数叫做质数。Torry突然想到一个问题,前10、100100010000……个质数的乘积是多少呢?他把这个问题告诉老师。老师愣住了,一时回答不出来。于是Torry求助于会编程的你,请你算出前n个质数的乘积。不过,考虑到你才接触编程不久,Torry只要你算出这个数模上50000的值。
 3 输入格式
 4   仅包含一个正整数n,其中n<=100000 5 输出格式
 6   输出一行,即前n个质数的乘积模50000的值。
 7 样例输入
 8 1
 9 样例输出
10 2
Torry的困惑-素数(质数)
 1 #include <iostream>
 2 
 3 using namespace std;
 4 bool prime(int n) //判断是否为素数
 5 {
 6   int i;
 7   for(i=2;i*i<n;i++)
 8       if(n%2==0)   break;
 9   if(i*i<n)    return false;
10   else    return true;
11 }
12 int main()
13 {
14   int i,j,n,sum,ans;
15   bool p[100001]={0};
16   while(cin>>n){
17   ans = 1;
18   sum = 0;
19   i = 2;
20   while(sum<n){
21   if(!p[i] && prime(i)){ //判断该数i是否为素数
22   ans = ans*i%50000;
23   sum++;
24   for(j=i+i;j<=100000;j+=i) //去掉不为素数的元素
25       p[j]=true;
26   }
27   i++;
28   }
29   cout<<ans<<endl;
30   }
31   return 0;
32 }
题解
 1 问题描述
 2 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:
 3 00000
 4 00001
 5 00010
 6 00011
 7 00100
 8 请按从小到大的顺序输出这32种01串。
 9 输入格式
10 本试题没有输入。
11 输出格式
12 输出32行,按从小到大的顺序每行一个长度为5的01串。
01子串
 1 #include<stdio.h>      
 2 int main()      
 3 {   int i,j,k,l,m;   
 4     for(i=0;i<=1;i++){      
 5         for(j=0;j<=1;j++){      
 6             for(k=0;k<=1;k++){      
 7                 for(l=0;l<=1;l++){      
 8                     for(m=0;m<=1;m++){      
 9                         printf("%d%d%d%d%d\n",i,j,k,l,m);      
10                     }      
11                 }      
12             }      
13         }      
14     }      
15     return 0;      
16 }  
题解
 1 问题描述
 2   求出区间[a,b]中所有整数的质因数分解。
 3 输入格式
 4   输入两个整数a,b。
 5 输出格式
 6   每行输出一个数的分解,形如k=a1*a2*a3...(a1<=a2<=a3...,k也是从小到大的)(具体可看样例)
 7 样例输入
 8 3 10
 9 样例输出
10 3=3
11 4=2*2
12 5=5
13 6=2*3
14 7=7
15 8=2*2*2
16 9=3*3
17 10=2*5
18 提示
19   先筛出所有素数,然后再分解。
20 数据规模和约定
21   2<=a<=b<=10000
分解质因数
 1 #include <iostream>  
 2 using namespace std;  
 3 int isprime(int n) {  
 4     if(n <= 1)  
 5         return 0;  
 6     else if(n == 2 || n == 3)  
 7         return 1;  
 8     else {  
 9         for(int i = 2; i * i < n; i++) {  //判断是否为素数
10             if(n % i == 0) {  
11                 return 0;  
12             }  
13         }  
14         return 1;  
15     }  
16 }  
17 int main() {  
18     int a, b;  
19     cin >> a >> b;  
20     for(int i = a; i <= b; i++) {  
21         int temp = i;  
22         cout << i << "=";  
23         int flag = 0;  
24         while(temp != 1) {  
25             for(int j = 2; j <= temp; j++) {  
26                 if(isprime(j) && temp % j == 0) {  
27                     temp = temp / j;  
28                     if(flag == 1)  
29                         cout << "*";  
30                     cout << j;  
31                     flag = 1;  
32                     break;  
33                 }  
34             }  
35         }  
36         cout << endl;  
37     }  
38     return 0;  
39 }
题解
posted @ 2017-06-04 15:56  _春华秋实  阅读(1022)  评论(0)    收藏  举报