Brute force(暴力法)

一、何谓暴力法

    暴力法,也叫穷举法。它要求设计者找出所有可能的方法,然后选择其中的一种方法,若该方法不可行则试探下一种可能的方法。该方法逻辑清晰、简单,编写程序简洁。在某些情况下,算法规模不大时,使用优化的算法没有必要,而且某些优化算法本身较为复杂,在规模不大时可能因为复杂的算法浪费时间,反而不如简单的蛮力搜索。使用暴力法的几种情况:

  1. 搜索所有的解空间和路径;2. 直接进行计算;3. 在问题规模不是很大的情况下,现实问题的模拟与仿真。

二、搜索所有的路径和解空间

    使用暴力方法将所有的可能解列出来,看这些解是否满足要求或者条件,从中选择出符合要求的解。

    例1:Safecracker

    这个题目可以用暴力法解决,只需要测试满足的解即可。值得注意的是需要考虑取值范围和多解时候的情况。代码与ZLG的差不多。

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 string str;
 7 
 8 bool cmp (int i,int j) { return (i>j);}
 9 
10 int cal(int y, int w, int v, int x, int z)
11 {
12      v -= 64, w -= 64, x -= 64, y -= 64, z -= 64;
13      return (v - w*w + x*x*x - y*y*y*y + z*z*z*z*z);
14 }
15 
16 bool GetSol(int t, string s){
17     int len;
18     int max, min;
19     len = s.length();
20     min = cal(s[0],s[1],s[len-3],s[len-2],s[len-1]);
21     max = cal(s[len-1],s[len-2],s[2],s[1],s[0]);
22     if( t> max && t < min)
23         return false;  //no solutions
24 
25     int vis[len];
26     for(int i = 0; i < len; i++) vis[i] = 0;
27     
28     for(int a=0; a<len; a++){
29         vis[a] = 1;
30         for(int b=0; b<len; b++){
31             if(!vis[b]){
32                 vis[b] = 1;
33                 for(int c=0; c<len; c++){
34                     if(!vis[c]){
35                         vis[c] = 1;
36                         for(int d=0; d<len; d++){
37                             if(!vis[d]){
38                                 vis[d] = 1;
39                                 for(int e=0; e<len; e++){
40                                     if(!vis[e] && t == cal(s[d], s[b], s[a], s[c], s[e])){
41                                         cout <<s[a]<<s[b]<<s[c]<<s[d]<<s[e]<<endl;
42                                         return true;
43                                     }
44                                 }
45                                 vis[d] =0;
46                             }
47                         }
48                         vis[c] = 0;    
49                     }
50                 }
51                 vis[b] = 0;
52             }    
53         }
54         vis[a] = 0;    
55     }
56     return false;
57 }
58 
59 int main(int argc, char *argv[])
60 {    
61     int t;
62     bool flag;
63     while(cin>>t && cin>>str){
64         if(t==0 && str=="END") break;
65         
66         sort(str.begin(),str.end(),cmp); //排序
67         flag = GetSol(t, str);
68         
69         if(!flag)
70             cout <<"no solution"<<endl;
71     }
72 
73 
74     return 0;
75 }
View Code

三、枚举所有的情况

    例2:2^x mod n = 1

    这个题目可以将所有的情况例举一次,然后去判断。另外注意2^x可能会超出long long类型,又因为2×s mod n = 2x (s mod n),因此所写的程序如下:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     int n,flag;
 8     long s;
 9     
10     while(cin>>n){    
11         flag =0;
12         s=1;            
13           for(int x=1;x<n+1;x++){
14             s *= 2;
15             s %= n;
16             if(s == 1){
17                 flag = x;
18                 break;                    
19             }
20         }
21         if(flag!=0)
22             cout<<"2^"<<flag<<" mod "<<n<<" = 1"<<endl;
23         else
24             cout<<"2^?"<<" mod "<<n<<" = 1"<<endl;
25     }
26 
27     return 0;
28 }
View Code

    另外一种枚举的写法:

#include<stdio.h>

int main(void)
{
    int n;
    while(~scanf("%d",&n)){
        if(n == 1 || n % 2 == 0){
            printf("2^? mod %d = 1\n", n);
            continue;
        }
        int k = 1, ans = 2;
        while(ans != 1){
            ans = ans *2 % n;
            k++;
        }
        printf("2^%d mod %d = 1\n", k, n);
    }
    return 0;
}
View Code

    例3: Fibonacci Again

    这个题目实际上去枚举情况: 第一步不是直接计算,而是寻找规律,第二步在规律中枚举所有的情况即可。代码如下:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main(){
 6     long n;
 7     while(cin>>n){
 8         if(n%8==2 || n%8==6)
 9             cout << "yes" << endl;
10         else
11             cout << "no" << endl;
12     }
13     return 0;
14 }
View Code

、直接计算

    例4:Big Number

    这个题目主要利用log10的函数来直接计算就好。代码如下:

 1 #include <iostream>
 2 #include <math.h>
 3 
 4 using namespace std;
 5 
 6 int main(){
 7 
 8     int testCase, n;
 9     double sum;
10     cin >> testCase;
11     while(testCase--){
12         cin >> n;
13         sum = 0;
14         for(int i=1; i<=n; i++){
15             sum += log10(i);
16         }
17         cout << (int)sum+1 <<endl;
18     }
19 
20     return 0;
21 }
View Code

四:模拟与仿真

    例5:Buildings

    这个可以算水题,将输入的东西进行判断是否为1,如果为1的话就可以累加。代码如下:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     int T,n,m, k, ans;
 8     cin >> T;
 9     
10     while(T--){
11         cin >>n >>m;
12         ans = 0;
13         for(int i=0; i<n; i++){
14             for(int j=0; j<m; j++){
15                 cin >> k;
16                 if(k) ans++;
17             }
18         }
19         cout << ans <<endl;    
20     }
21     return 0;
22 }
View Code

    例6:Crashing Robots

    这个当习题。

 

转载于:https://www.cnblogs.com/linspirit/articles/3777783.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值