麻将(mahjong)
“為什么, 你們的力量在哪里得到如此地 ”
“我們比 1 分鐘前的我們還要進步, 雖然很微小, 但每轉一圈就會前進一寸。這就是鉆頭啊!” “那才是通向毀滅的道路。為什么就沒有意識到螺旋族的極限”
“那是你的極限。那只不過是在封閉的宇宙里, 象國王一樣將其他生命困住的你自己的極限而已。給我記好了, 我們的鉆頭將在這片宇宙中鉆開風洞。已經倒下的人們的愿望, 和后繼邇來的人們的希望。將這兩股思念交織成二重螺旋, 鑿出馳騁于明天的未來之路。這就是天元突破! 這就是 Gurren Lagann! 我的鉆頭是開創天際的鉆頭!”
終于,GranzeBorma 爆炸了。
“那么, 這片宇宙, 一定要保護好 ”
西蒙回答了 Anti-Spiral 這最后的一句話。“那是當然。人類還沒有愚蠢到那種地步”
Anti-Spiral 的終結, 化做為銀河各地的螺旋族歡喜的信息, 從四面八方傳來。
——在那這之后要說的話, 也所剩無幾了。
回到地球后的妮亞與西蒙結了婚, 并且永遠地離開了, 因為她是由 Anti-Spiral 創造出來的假想生命。但是在離別的那一瞬間, 妮亞與西蒙依然互相微笑著。
時光飛逝, 在地球大總統羅修的努力下, 全銀河螺旋力和平利用會議得以召開。超銀河大 Gurren 承載著地球的代表踏上旅途。還有通過新聞, 想起與大家的種種回憶的昔日大 Gurren 團的成員。
然后——
在一個遠離市區的地方, 有一個男人教會了少年使用鉆頭的方法。夜空中,Gurren Lagann 畫出螺旋的軌道, 從男人與少年的頭頂飛過。在那前方, 螺旋的朋友們正在那片群星中等待著我們。
終于有一天,在這顆古老的星球上誕生了一種了不起的游戲——mahjong 游戲只使用萬、筒、條三種花色,即以下 27 種牌面:
      
每一種牌面各有 4 張,總計 108 張牌。
胡牌的牌型為 4 個“句子”和 1 副“將牌”。
句子一共以下有兩種形式:
三張相同花色且連續的牌,如圖1
三張相同的牌,如圖2
      
將牌:兩張相同的牌,如:
      
當手牌構成 4
個“句子”和 1 副“將牌”時則構成胡牌牌型,如:
聽牌:當 13 張手牌再加上某一張就能成胡牌牌型時稱之為聽牌,如:
聽牌時再加上某一張就能胡牌,那我們就稱那張牌是聽的牌 如圖牌型就聽三、六條
現在你手中有 14 張牌,求打出第幾張牌會使得你聽得牌的張數最多,最多聽多少張牌
Input
一行 14 張牌,用空格隔開
1..9 表示牌上數字,w、p、s 分別表示萬、筒、條,如
1s 表示一條
Output
一行兩個數用空格隔開,分別表示打出第幾張牌會使得你聽得牌的張數最多以及最多聽多少張牌 如果有多張牌使得打出后聽得牌一樣多,輸出標號最靠前的
Example
| mahjong.in | mahjong.out | |||||||||||
| 1s 7p | 2s 7p | 3s | 4s | 6s | 6s | 6s | 2w | 2w | 2w | 3p | 3p | 1 4 | 
| 1s 8p | 1s 9p | 1s | 2s | 3s | 4s | 5s | 6s | 6p | 6p | 7p | 8p | 12 10 | 
Explanation
樣例 1:無論是打出 1s 還是 4s 都是聽 3p 和 7p,而 3p 共有 4 張,手中已經有 2 張,牌堆中還剩 2
張,7p 也有 4 張,手中已經有 2 張,牌堆中還剩 2 張,所以打出 1s 聽 4 張樣例 2:打出 6p 或 9p 聽 7p 共 3 張,打出 8p 聽 1s、4s、7s、6p 共 10 張
Scoring
對于 30% 的數據,胡牌牌型中的句子只會是三張相同的牌。
對于另外 20% 的數據,14 張手牌同屬于萬、筒、條其中的某一種。注:測試點 6 時限 2s
這次比賽最大的收獲——學會了打麻將!
思路:
像這樣棋牌的暴搜,方法不難,難在用搜索來寫出方法。因為給定的數量,數據量小,但枚舉各種情況的步驟復雜,最適合暴搜啦
按照三種牌的類型和9個點數依次搜索,當前點數和類型的牌搜完指的是它和之前點數的牌都得到應有的安排,每層搜索都必須確保搜完才能進入下一層,否則,如果有牌沒法和別的牌湊成句子或將,就證明當前情況不能胡牌;
用全局變量flag記錄是否胡牌,當某種情況可以胡牌時,賦值true,之后回溯時再不進行任何向下搜索,直接返回退出DFS;
用變量z記錄是否已經湊出將牌,如果已經湊出,此后不再考慮將牌的情況;
分以下幾種情況討論:
  <1>當前搜到了點數10,即當前類型的牌搜完了,繼續搜下一種類型的牌,如果已經徹底搜完了,就證明可以胡牌;
  <2>當前點數和類型沒有牌,繼續下一層搜索;
<3>當前點數小于等于7并且其后兩個點數都有牌,那么這三張牌可以當做一個句子;
<4>當前點數和類型牌的張數大于3,那么這三張牌可以當做一個句子;
<5>當前點數和類型牌的張數大于2,那么這兩張牌可以當做一副將牌;
如何計算、輸出結果不贅述,但要注意要輸出標號最靠前的,在輸入記錄編號時只記錄最前的即可
興學長噠~
#include<cstdio>
int sl[3][10],ans,mx,s;
struct xh
{
    int xh,z;
}x[30];
bool dfs(int a,int b,int c,int d)
{
    if(c&&d==4) return 1;
    if(a==3) return 0;
    bool re;
    int ta,tb;
    if(b==9) tb=1,ta=a+1;
    else tb=b+1,ta=a;
    
    if(sl[a][b]>1&&!c)
    {
        sl[a][b]-=2;
        re=dfs(a,b,1,d);
        sl[a][b]+=2;
        if(re) return 1;
    }
    
    if(sl[a][b]>2)
    {
        sl[a][b]-=3;
        re=dfs(ta,tb,c,d+1);
        sl[a][b]+=3;
        if(re) return 1;
    }
    
    if(b>2&&sl[a][b]&&sl[a][b-1]&&sl[a][b-2])
    {
        sl[a][b]--,sl[a][b-1]--,sl[a][b-2]--;
        re=dfs(a,b,c,d+1);
        sl[a][b]++,sl[a][b-1]++,sl[a][b-2]++;
        if(re) return 1;
    }
    return dfs(ta,tb,c,d);
}
int main()
{
//    freopen("mahjong.in","r",stdin),freopen("mahjong.out","w",stdout);
    char c;
    while(scanf("%d%c",&x[++s].xh,&c)!=EOF)
    {
        if(c=='p') x[s].z=2;
        else x[s].z=c=='w';
        sl[x[s].z][x[s].xh]++;
        if(s==14) break; 
    }
    for(int i=1;i<s;++i)
    {
        int jl=0;
        sl[x[i].z][x[i].xh]--;
        for(int j=0;j<3;++j)
            for(int k=1;k<10;++k)
            {
                sl[j][k]++;
                if(dfs(0,1,0,0)) jl+=5-sl[j][k];
                sl[j][k]--;
            }
        sl[x[i].z][x[i].xh]++;
        if(jl>mx) mx=jl,ans=i;
    }
    printf("%d %d",ans,mx);
    return 0;
}
注釋代碼^-^
#include<cstdio>
int a[4][10],b[4][10],ans1,ans2;
bool flag;
void dfs(int x,int y,bool z)//(z表示是否已有將牌)
{
    if(y==10) //如果當前點數到頭 
    {
        if(x==4) flag=true; //如果當前花色到頭
        else if(!flag) dfs(x+1,1,z);
        return;
    }
    if(!a[x][y])
    {
        dfs(x,y+1,z);
        return;
    }
    
    if(y<=7) //找順子
    {
        if(a[x][y+1]&&a[x][y+2])
        {
            --a[x][y];--a[x][y+1];--a[x][y+2];
            if(!flag)
            {
                if(a[x][y]) dfs(x,y,z);
                else dfs(x,y+1,z);
            }
            ++a[x][y];++a[x][y+1];++a[x][y+2];
        }
    }
    
    if(a[x][y]>=3) //找三同 
    {
        a[x][y]-=3;
        if(!flag)
        {
            if(a[x][y]) dfs(x,y,z);
            else dfs(x,y+1,z);
        }
        a[x][y]+=3;
    }
    
    if(a[x][y]>=2&&!z) //找將牌,將牌已有則不再找 
    {
        a[x][y]-=2;
        if(!flag)
        {
            if(a[x][y])dfs(x,y,1);
            else dfs(x,y+1,1);
        }
        a[x][y]+=2;
    }
    return;
}
int main()
{
    int t1;char t2;
    for(int i=1;i<=14;++i)
    {
        scanf("%d%c",&t1,&t2); //t1點數,t2花色 
        if(t2=='w')
        {
            ++a[1][t1]; //a[i][j] 記錄 i 點數,j 花色的數量 
            if(!b[1][t1]) b[1][t1]=i; //b[i][j] 記錄該牌的次序 
        }
        else if(t2=='p')
        {
            ++a[2][t1];
            if(!b[2][t1]) b[2][t1]=i;
        }
        else
        {
            ++a[3][t1];
            if(!b[3][t1]) b[3][t1]=i;
        }
    }
    
    for(int i=1;i<=3;++i)
    {
        for(int j=1;j<=9;++j)
        {
            if(!a[i][j])continue; //打出一張a[i][j],所以不能為0 
            --a[i][j];
            t1=0;
            for(int k=1;k<=3;++k) //枚舉所有能摸到的牌 
            {
                for(int l=1;l<=9;++l)
                {
                    ++a[k][l]; //摸到a[k][l] 
                    dfs(1,1,false);
                    if(flag) //如果能胡牌 
                    {
                        t1+=4-a[k][l]+1; //加上能聽的a[k][l]的數量 
                        flag=false;
                    }
                    --a[k][l];
                }
            }
            
            if(t1>ans1)
            {
                ans1=t1;
                ans2=b[i][j];
            }
            ++a[i][j];
        }
    }
    
    printf("%d %d
",ans2,ans1);
    return 0;
}
從0到1很難,但從1到100很容易
總結
以上是生活随笔為你收集整理的麻将(mahjong)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: VMware虚拟机走主机代理
- 下一篇: win10此电脑不见了_教程 | win
