【算法】暴力求解法
简单枚举
简单枚举的基本思路就是, 枚举起点, 枚举终点, 然后里面再去做运算, 例题:
对于这道题, 如果使用暴力枚举法的话, 就要枚举每一个元素作为起点, 再枚举每个元素前面的元素作为终点的情况, 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include<iostream> using namespace std;
int main(){ int n; int ncase=0; while(cin>>n){ long long ans = 0; long long num[100]; for(int i=0;i<n;i++){ cin>>num[i]; } for(int i=0;i<n;i++){ for(int j=0; i+j<n; j++){ long long tmp = 1; for(int k=0; k<j; k++){ tmp *= num[i+k]; } if(tmp>ans){ ans = tmp; } } } if(ans<0){ ans = 0; } cout<<"Case #"<<++ncase<<": The maximum product is"<<ans<<"."<<endl; } return 0; }
|
这里给一个值范围的表格:
排列法枚举
排列法进行枚举可以使用 STL 中的 next_permutation()
, 复杂度为 O(n), 用法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include<algorithm>
next_permutation() prev_permutation()
int num[4]={1,2,3,4};
do{ cout<<num[0]<<num[1]<<num[2]<<num[3]<<endl }while(next_premutation(num,num+4));
|
例题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<iostream> #include<algorithm> using namespace std;
int main(){ int n,m; while(cin>>n>>m){ int num[1010]; for(int i=1;i<=n;i++){ num[i]=i; } int tmp=1; do{ if(tmp==m) break; tmp++; }while(next_permutation(num+1,num+n+1)); for(int i=1;i<n;i++){ cout<<num[i]<<" "; } cout<<num[n]<<endl; } return 0; }
|
二进制法
常用的位运算符有 左移(<<) 和 右移(>>), 位运算操作不建议对负数操作
其中 x<<k
表示将 x 转换为二进制再左移 k 位补零, 十进制下的运算为 $x*2^k$.
x>>k
在十进制下的运算为 $x/2^k$.
位运算常用于状态压缩, 比如有 5 个物品, 我们可以用二进制数 01000
表示只有第 2 个物品被取了, 其他物品没有被取. 当需要枚举的子集或者超集的时候, 就可以使用状态压缩.
以下是常用的位运算技巧:
例题:
这道题可以使用二进制枚举来做
首先是如何用二进制去表示每一个排列组合, 对于 $n$ 个正整数, 从 $0$ 遍历到 $2^n-1$ 就可以表示所有的组合了, 二进制下就是 $00..00$ 遍历到 $11..11$, 然后使用位运算去获取所有的排列, 这里用的位运算是 (i&(1<<j))
表示获取 i
的 第 j
位, 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include<iostream> #include<algorithm> #include<vector> #include<iomanip>
bool cmp(vector<int> a, vector<int> b){ for(int i=0; i<a.size();i++){ if(a[i]!=b[i]){ return a[i]<b[i]; } } }
int main(){ int n,r; cin>>n>>r; vector<vector<int>> res; for(int i=0; i<(1<<n); i++){ cnt=0; for(int j=0; j<=n; j++){ if(i&(1<<j)){ cnt++; } } if(cnt==r){ vector<int>tmp; for(int j=0; j<=n;j++){ if(i&(1<<j)){ tmp.push_back(j+1); } } res.push_back(tmp); } sort(res.begin(),res.end(),cmp); for(vector<int> a : res){ for(int b : a){ cout<<setw(3)<<b; } cout<<endl; } } return 0; }
|