1. 程式人生 > >2015第六屆藍橋杯C++B組第七題:牌型種數

2015第六屆藍橋杯C++B組第七題:牌型種數

題目:

牌型種數

小明被劫持到X賭城,被迫與其他3人玩牌。
一副撲克牌(去掉大小王牌,共52張),均勻發給4個人,每個人13張。
這時,小明腦子裡突然冒出一個問題:
如果不考慮花色,只考慮點數,也不考慮自己得到的牌的先後順序,自己手裡能拿到的初始牌型組合一共有多少種呢?

請填寫該整數,不要填寫任何多餘的內容或說明文字。

思路:1.一開始想的是直接求53張牌的全排列然後擷取前13張排序後存入set,最後輸出set元素個數,但這個要算好久,然後試了下深搜,還是要算好久,除錯後發現是因為有好多都是可以算成一組的,只是位置不同,所有最後加了個判斷,是生成的陣列嚴格升序,不然不繼續搜尋,這樣速度就很快了。 2.可以直接13重迴圈,沒個元素4張,只要張數總數為13就算一種。

答案:3598180

程式碼1(推薦的方法):

// 牌型種數
#include <bits/stdc++.h>
using namespace std;

int an[13];
int res[13];
int visited[13];
set<string> sset;

long cnt(0);

void init()
{
    for(int i=0;i<13;++i) an[i]=i+1;

    memset(visited,0,sizeof(int)*13);
}


void f(int m)
{
    if(m==0) {
        cnt += 1
; return ; }else { for(int i=0;i<13;++i) { if(visited[i]<4){ res[13-m]=an[i]; // 這個判斷很重要,避免重複排列,不然要算好久 if(res[13-m]<res[12-m]&&res[12-m]!=0) continue; visited[i]+=1; f(m-1); visited[i]-=1
; } } } } int main() { init(); f(13); cout << cnt << endl; return 0; }

程式碼2(迴圈,簡單直接,但是速度沒有上面深搜快):

#include <bits/stdc++.h> 
using namespace std;  

int main()  
{  
    int a[13],cnt(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)  
                                                        {  
                                                            cnt += 1;  
                                                        }  
                                                    }  
                                                }  
                                            }  
                                        }  
                                    }  
                                }  
                            }  
                        }  
                    }  
                }  
            }  
        }  
    }  

    cout << cnt << endl;


    return 0;  
}

程式碼3(最初的思路,過於暴力,算不出來,要算好久)

// 牌型種數
#include <bits/stdc++.h>
using namespace std;

int an[52];
set<string> sset;

void init()
{
    for(int i=0;i<4;++i) {
        for(int j=0;j<13;++j) {
            an[13*i+j] = j+1; 
        }
    }

}

string a2s()
{
    // 擷取前13張牌
    ostringstream ostr;
    sort(an,an+13);
    for(int i=0;i<13;++i) ostr << an[i];
    return ostr.str(); 
}

int main()
{


    long cnt(0);

    string ts;
    do {
        ts = a2s();
        sset.insert(ts);
    }while(next_permutation(an,an+52));

    cnt = sset.size();

    cout << cnt << endl;

    return 0;
}