zoukankan      html  css  js  c++  java
  • 牌型种数|2015年蓝桥杯B组题解析第七题-fishers

    牌型种数

    小明被劫持到X赌城,被迫与其他3人玩牌。
    一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。
    这时,小明脑子里突然冒出一个问题:
    如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?

    请填写该整数,不要填写任何多余的内容或说明文字。

    答案:3598180

    思路一:暴力法,12层循环枚举取得各个牌得数量(想不到其它方法,这种方法最有效!)

    思路二:递归求组合数,从52张牌中选出13张,

    代码一:暴力枚举

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int main()
    {
     int a[13]; 
     static int count;
     int ans = 0;
     for(a[0]=0; a[0]<=4; a[0]++)
     {
      for(a[1]=0; a[1]<=4; a[1]++)
      {
       for(a[2]=0; a[2]<=4; a[2]++)
       {
        for(a[3]=0; a[3]<=4; a[3]++)
        {
         for(a[4]=0; a[4]<=4; a[4]++)
         {
          for(a[5]=0; a[5]<=4; a[5]++)
          {
           for(a[6]=0; a[6]<=4; a[6]++)
           { 
            for(a[7]=0; a[7]<=4; a[7]++)
            {
             for(a[8]=0; a[8]<=4; a[8]++)
             {
              for(a[9]=0; a[9]<=4; a[9]++)
              {
               for(a[10]=0; a[10]<=4; a[10]++)
               {
                for(a[11]=0; a[11]<=4; a[11]++)
                {
                 for(a[12]=0; a[12]<=4; a[12]++)
                 {
                  if(a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9]+a[10]+a[11]+a[12]==13)
                  {
                   count++;
                   ans = count;
                  }
                 }
                }
               }
              }
             }
            }
           }
          } 
         }
        }
       }
      }
     }
     cout<<ans<<endl;
     return 0;
    }
    
    

    代码二:dfs,递归求组合数,

    #include<iostream>  
    #include<algorithm>  
    #include<cmath>  
    #include<cstdio>  
    #include<cstring>  
    using namespace std;  
    int sum=0;  
    
    //两个参数:pos表示牌的号码1~13 cnt表示当前选择的是第几张牌
    //从第1号牌 开始选第一张 
    void dfs(int pos, int cnt){  
    	//选够了13张牌 sum总数加1 
        if(cnt==14){  
            sum++;  
            return;  
        }
        //选到第14号牌了 还没有选够13张 return 
        if(pos==14){  
            return;  
        }  
        int num=min(14-cnt,4);//min取两者中的小值   这句话剪枝! 
        
        for(int i=0;i<=num;i++){  
            dfs(pos+1,cnt+i); //cnt+i表示当前手里已经选好的牌的数目 
        }  
        return;  
    }  
    int main(){  
        dfs(1,1); //增加参数 2个参数:从第1号牌 开始选第一张 不选、选1张...选4张 
        printf("%d
    ",sum);  
        return 0;  
    }  
    

    代码三:dfs回溯,(超时)。

    #include<iostream>
    using namespace std;
    
    //回溯法:按字典序选择,但是会超时! 
    
    int have[20];
    int sum = 0;
    int a[15];
    
    
    void init(){
    	for(int i=1;i<=14;i++){
    		have[i] = 0;
    	}
    }
    
    
    //下面是错误写法:时间复杂度太高 n^n 这里是5^13次方(10亿)
    //递归程序中不能有太多循环! 
    void dfs(int k){
    	if(k==5){
    		//判断是否有这个组合 
    		sum++;
    		for(int j=1;j<14;j++){
    			cout<<a[j]<<" ";
    		}
    		cout<<endl;
    		return;
    	}
    	//循环13次 时间复杂度太高 
    	for(int i=1;i<=13;i++){
    		if(have[i] < 4){
    			have[i]++; 
    			a[k] = i; 
    			dfs(k+1); 
    			have[i]--;
    		}
    	} 
    }
    
    int main(){
    	init();
    	dfs(1);
    	cout<<sum<<endl;
    } 
    

    /这道题目给我的思考是,
    在用暴力法(dfs递归)的时候直接多想几种可能,
    多想几种方案(这里选04张牌,而不是用回溯法从113张中选)
    这样可以很大程度上节约时间
    /

  • 相关阅读:
    SQL之mysql常用操作语句(入门级)
    总结了一些指针易出错的常见问题(七)
    C++之类和对象课后习题1
    SQL之50个常用的SQL语句
    SQL之经典SQL语句大全
    C语言之计算字符串最后一个单词的长度,单词以空格隔开
    spring之HttpInvoker
    Java之解压流(ZipInputStream)
    jetty之嵌入式开发
    java之压缩流(ZipOutputStream)
  • 原文地址:https://www.cnblogs.com/fisherss/p/10300253.html
Copyright © 2011-2022 走看看