首页 > 其他 > 详细

洛谷 P2668 斗地主

时间:2018-08-06 12:42:23      阅读:150      评论:0      收藏:0      [点我收藏+]

题意简述

读入一组牌,求最少需要多少次出牌可以将它们打光。

题解思路

暴力搜索+剪枝

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, t, ax, bx, card[20], now, ans;
void dfs();
void shunzi(int x, int y);
int main()
{
    scanf("%d%d", &t, &n);
    for (int i = 1; i <= t; ++i)
    {
        ans = n;
        memset(card, 0, sizeof(card));
        for (int j = 1; j <= n; ++j)
        {
            scanf("%d%d", &ax, &bx);
            if (ax == 0)
                ax = 16;
            if (ax < 3)
                ax += 13;
            card[ax] ++;
        }
        dfs();
        printf("%d\n", ans);
    }
}
void getstra(int x, int y)                                   //判断顺子,x为组数,y为每组个数
{
    for (int i = 3; i <= 15 - y; ++i)
    {
        int cnt = 0;
        for (int j = i; j <= 14; ++j)
            if (card[j] >= x)
                cnt ++;
            else break;
        if (cnt >= y)
        {
            for (int j = i; j <= i + cnt - 1; ++j)
                card[j] -= x;
            dfs();
            for (int j = i; j <= i + cnt - 1; ++j)
                card[j] += x;
        }
    }
}
void dfs()
{
    int cnt = 0;
    for (int i = 3; i <= 15; ++i)                 //判断单出
        cnt += (card[i] + 3) / 4;
    cnt += (card[16] + 1) / 2;
    if (now >= ans)                                //剪枝
        return;
    ans = min(ans, cnt + now);
    now ++;
    getstra(3, 2);                                    //搜索顺子
    getstra(2, 3);
    getstra(1, 5);
    for (int i = 3; i <= 15; ++i)                //搜索4带
    {
        if (card[i] >= 4)
        {
            card[i] -= 4;
            for (int j = 3; j <= 16; ++j)
                for (int k = 3; k <= 16; ++k)
                {
                    if ((j - i & i - k & k - j) && card[j] == card[k] && card[j] && card[k])
                    {
                        card[j] --;
                        card[k] --;
                        dfs();
                        if (card[j] && card[k])
                        {
                            card[j] --;
                            card[k] --;
                            dfs();
                            card[j] ++;
                            card[k] ++;
                        }
                        card[j] ++;
                        card[k] ++;
                    }
                }
            card[i] += 4;
        }
    }
    for (int i = 3; i <= 15; ++i)              //搜索3带
    {
        if (card[i] >= 3)
        {
            card[i] -= 3;
            for (int j = 3; j <= 16; ++j)
                if ((j - i) && card[j])
                {
                    card[j] --;
                    dfs();
                    if (card[j])
                    {
                        card[j] --;
                        dfs();
                        card[j] ++;
                    }
                    card[j] ++;
                }
            card[i] += 3;
        }
    }
    now --;
}

洛谷 P2668 斗地主

原文:https://www.cnblogs.com/xuyixuan/p/9429577.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!