zoukankan      html  css  js  c++  java
  • (二进制枚举或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;
    }
  • 相关阅读:
    [BJOI2019] 光线
    [BJOI2019]奥术神杖
    [HNOI2014]江南乐
    [SDOI2018]荣誉称号
    [APIO2015]雅加达的摩天楼
    [TJOI2015]线性代数
    【CF163E 】e-Government
    【CF917D】Stranger Trees
    网络流(四)dinic算法
    网络流(三)最大流最小割定理
  • 原文地址:https://www.cnblogs.com/xusi/p/12436074.html
Copyright © 2011-2022 走看看