noip2015 斗地主


P2668 斗地主

    • 291通過
    • 2.5K提交
  • 題目提供者洛谷OnlineJudge
  • 標簽搜索/枚舉2015NOIp提高組
  • 難度提高+/省選-

提交該題 討論 題解 記錄

最新討論

題目描述

牛牛最近迷上了一種叫斗地主的撲克游戲。斗地主是一種使用黑桃、紅心、梅花、方片的A到K加上大小王的共54張牌來進行的撲克牌游戲。在斗地主中,牌的大小關系根據牌的數碼表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色並不對牌的大小產生影響。每一局游戲中,一副手牌由n張牌組成。游戲者每次可以根據規定的牌型進行出牌,首先打光自己的手牌一方取得游戲的勝利。

現在,牛牛只想知道,對於自己的若干組手牌,分別最少需要多少次出牌可以將它們打光。請你幫他解決這個問題。

需要注意的是,本題中游戲者每次可以出手的牌型與一般的斗地主相似而略有不同。

具體規則如下:

輸入輸出格式

輸入格式:

 

第一行包含用空格隔開的2個正整數Tn,表示手牌的組數以及每組手牌的張數。

接下來T組數據,每組數據n行,每行一個非負整數對aibi表示一張牌,其中ai示牌的數碼,bi表示牌的花色,中間用空格隔開。特別的,我們用1來表示數碼A,11表示數碼J,12表示數碼Q,13表示數碼K;黑桃、紅心、梅花、方片分別用1-4來表示;小王的表示方法為01,大王的表示方法為02。

 

輸出格式:

 

共T行,每行一個整數,表示打光第i手牌的最少次數。

 

輸入輸出樣例

輸入樣例#1:
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
輸出樣例#1:
3
輸入樣例#2:
1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
輸出樣例#2:
6

說明

樣例1說明

共有1組手牌,包含8張牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通過打單順子(方片7,方片8,黑桃9,方片10,黑桃J),單張牌(黑桃5)以及對子牌(黑桃A以及方片A)在3次內打光。

對於不同的測試點, 我們約定手牌組數T與張數n的規模如下:

數據保證:所有的手牌都是隨機生成的。

分析:重新做這道題,滿滿都是淚啊,在考場上打了個30分暴力,結果爆0了......步入正題,這道題一看就知道肯定是爆搜,但是情況實在太多,怎么辦?注意到對次數有影響的就是順子,如果不打順子,那么最少的出牌次數是一定的,所以dfs搜索出三順子二順子和順子后的總步數,然后更新答案即可.花色在本題中無用.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 25;
int a[maxn], num[maxn];
int n, t, ans;

int chupai()
{
    memset(num, 0, sizeof(num));
    for (int i = 0; i <= 13; i++)
        num[a[i]]++;
    int tot = 0;
    while (num[4] && num[2] > 1)
    {
        num[4]--;
        num[2] -= 2;
        tot++;
    }
    while (num[4] && num[1] > 1)
    {
        num[4]--;
        num[1] -= 2;
        tot++;
    }
    while (num[4] && num[2])
    {
        num[4]--;
        num[2]--;
        tot++;
    }
    while (num[3] && num[2])
    {
        num[3]--;
        num[2]--;
        tot++;
    }
    while (num[3] && num[1])
    {
        num[3]--;
        num[1]--;
        tot++;
    }
    return tot + num[1] + num[2] + num[3] + num[4];
}

void dfs(int step)
{
    if (step >= ans)
        return;
    int temp = chupai();
    if (temp + step < ans)
        ans = temp + step;
    for (int i = 2; i <= 13; i++)
    {
        int j = i;
        while (a[j] >= 3)
            j++;
        if (j - i >= 2)
        {
            for (int j2 = i + 1; j2 <= j - 1; j2++)
            {
                for (int k = i; k <= j2; k++)
                    a[k] -= 3;
                dfs(step + 1);
                for (int k = i; k <= j2; k++)
                    a[k] += 3;
            }
        }
    }
    for (int i = 2; i <= 13; i++)
    {
        int j = i;
        while (a[j] >= 2)
            j++;
        if (j - i >= 3)
        {
            for (int j2 = i + 2; j2 <= j - 1; j2++)
            {
                for (int k = i; k <= j2; k++)
                    a[k] -= 2;
                dfs(step + 1);
                for (int k = i; k <= j2; k++)
                    a[k] += 2;
            }
        }
    }
    for (int i = 2; i <= 13; i++)
    {
        int j = i;
        while (a[j] >= 1)
            j++;
        if (j - i >= 5)
        {
            for (int j2 = i + 4; j2 <= j - 1; j2++)
            {
                for (int k = i; k <= j2; k++)
                    a[k]--;
                dfs(step + 1);
                for (int k = i; k <= j2; k++)
                    a[k]++;
            }
        }
    }
}

int main()
{
    scanf("%d%d", &t, &n);
    while (t--)
    {
        memset(a, 0, sizeof(a));
        for (int i = 1; i <= n; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            if (x == 1)  //轉換掉A
                x = 13; 
            else
            if (x)
                x--;
            a[x]++;
        }
        ans = 1e9;
        dfs(0);
        printf("%d\n", ans);
    }

    return 0;
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM