(二进制枚举或dfs)李白打酒
话说大诗人李白,一生好饮。幸好他从不开车。一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:无事街上走,提壶去打酒。逢店加一倍,遇花喝一斗。这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
思路:因为最后一次一定是遇见花,问题可以转化为枚举14个0组成的数组中,任意选5个位置将0变成1,然后遍历该数组,为0就n--,遇到1就n=n*2,最后n=1结果就加一
解法1:(dfs)
#include <cstdio> #include <string.h> #include <iostream> #include <algorithm> #include <sstream> #include <math.h> using namespace std; const int inf=0x7fffffff; const long long mod=1e9+7; const double PI=acos(-1); bool vis[14]; int a[105]; int n; int ans; void dfs(int pos,int f){ if(f==5){ //已经设置了5个位置的1 int co=2; for(int i=0;i<14;i++){ // 遍历vis数组,为0就co--,遇到1就co=co*2,最后co=1结果就加一 if(vis[i]) co=co*2; else co=co-1; } if(co==1){ ans++; } return; } for(int i=pos;i<14;i++){ //遍历vis数组,在任意5个位置设为1 if(!vis[i]){ vis[i]=1; dfs(i+1,f+1); vis[i]=0; } } } int main() { dfs(0,0); cout<<ans; return 0; }
解法2:(二进制枚举)
#include <cstdio> #include <string.h> #include <iostream> #include <algorithm> #include <sstream> #include <math.h> using namespace std; const int inf=0x7fffffff; const long long mod=1e9+7; const double PI=acos(-1); bool vis[14]; int a[105]; int n; int ans; int main() { int ans = 0; for (int i = 0; i < (1<<14); ++i) { //从14个0遍历到14个1 二进制遍历法 相当于14位01序列的全排列 int tot_1 = 0; int tot_0 = 0; int num = 2; for (int j = 0; j < 14; ++j) { if (i&(1 << j)) { // 这里判断二进制的i 从右数第 j + 1 位是否为 1 tot_1++; num = num * 2; } else { tot_0++; num = num - 1; } } if (tot_1 == 5 && tot_0 == 9 && num == 1) { ++ans; // 记录合法方案数 } } cout<<ans; return 0; }