HDU 4431 Mahjong 简单的DFS

题意:给出十三章牌,问有几种赢的方法。

思路:DFS枚举所有的情况,记得剪枝。

自己想得几组数据。

7
1s 1s 2s 2s 3s 3s 4s 4s 5s 5s 6s 6s 7s
3 1s 4s 7s
1s 1s 3s 3s 5s 5s 1p 1p 5m 5m 7c 7c 1c
1 1c
1s 2s 3s 2c 2c 2c 2p 3p 5m 6m 7m 1p 1p
2 1p 4p
1p 1p 2p 3p 4s 5s 6s 7c 7c 3s 3s 2m 2m
Nooten
1s 2s 3s 4s 5s 6s 7s 8s 9s 9s 9s 2c 3c
Nooten
1s 2s 3s 4s 5s 6s 7s 8s 9s 9s 9s 2c 2c
4 3s 6s 9s 2c
1s 9s 1m 9m 1p 9p 1c 2c 3c 4c 5c 6c 7c
13 1m 9m 1s 9s 1p 9p 1c 2c 3c 4c 5c 6c 7c


#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
#include <string>
#include <set>
#include <stack>

#define LL long long
#define EPS (1e-8)
#define Left true
#define Right false

using namespace std;

struct N
{
    int id,ty;
}s[15];

struct E
{
    int id;
    char ty;
}st[100000];

int mark[5][10];

bool dfs_con;

bool dfs(int t1,int t2,int eye,int r,int c)
{
    int i,j;

    if(dfs_con)
        return true;

    for(i = 1;i <= r; ++i)
    {
        for(j = 1;j < (i == r ? c : 9) ; ++j)
        {
            if(mark[i][j] != 0)
                return false;
        }
    }

    if(eye == 1 && mark[r][c] != 3 && mark[r][c] != 0 && ( (c == 9 && mark[r][c-1] == 0) || (c == 1 && mark[r][c+1] == 0) || (1 < c && c < 9 && mark[r][c+1] == 0 && mark[r][c-1] == 0)))
    {
        return false;
    }
    if(eye == 0 && mark[r][c] == 4 && mark[r][c] == 1 && ( (c == 9 && mark[r][c-1] == 0) || (c == 1 && mark[r][c+1] == 0) || (1 < c && c < 9 && mark[r][c+1] == 0 && mark[r][c-1] == 0)))
    {
        return false;
    }
    if(t1+t2 == 4 && eye)
    {
        dfs_con = true;
        return true;
    }

    for(i = r;i <= 4; ++i)
    {
        for(j = (i == r ? c : 1) ; j <= 9; ++j)
        {
            if(eye == 0)
            {
                if(mark[i][j] >= 2)
                {
                    mark[i][j] -= 2;
                    if(dfs(t1,t2,1,i,j) == true)
                        return true;
                    mark[i][j] += 2;
                }
            }
            if(mark[i][j] >= 3)
            {
                mark[i][j] -= 3;
                if(dfs(t1+1,t2,eye,i,j) == true)
                {
                    return true;
                }
                mark[i][j] += 3;
            }
            if(i != 4 && j <= 7 && mark[i][j] >= 1 && mark[i][j+1] >= 1 && mark[i][j+2] >= 1)
            {
                mark[i][j]--;
                mark[i][j+1]--;
                mark[i][j+2]--;
                if(dfs(t1,t2+1,eye,i,j) == true)
                {
                    return true;
                }
                mark[i][j]++;
                mark[i][j+1]++;
                mark[i][j+2]++;
            }
        }
    }
    return false;
}

bool Is_Win(N *p)
{
    int eye;
    int i,j;
    memset(mark,0,sizeof(mark));
    for(i = 1;i <= 14; ++i)
    {
        mark[p[i].ty][p[i].id]++;
    }

    eye = 0;

    for(i = 1;i <= 4; ++i)
    {
        for(j = 1;j <= 9; ++j)
        {
            if(mark[i][j] == 2)
            {
                eye++;
            }
            if(mark[i][j] >= 5)
                return false;
        }
    }

    if(eye == 7)
    {
        return true;
    }

    for(i = 1;i <= 3 && 1 <= mark[i][1] && 1 <= mark[i][9] ; ++i)
        ;

    if(i == 4)
    {
        for(i = 1;i <= 7 && 1 <= mark[4][i] ; ++i)
            ;
        if(i == 8)
        {

            for(i = 1;i <= 3 ; ++i)
            {
                if(2 == mark[i][1] || 2 == mark[i][9])
                    return true;
            }
            for(i = 1;i <= 7; ++i)
            {
                if(mark[4][i] == 2)
                    return true;
            }
        }
    }

    dfs_con = false;
    return dfs(0,0,0,1,1);
}

int main()
{
    int n,i;

    int top;

    scanf("%d",&n);
    char c;
    while(n--)
    {
        top = 0;
        E temp;
        for(i = 1;i <= 13; ++i)
        {
            scanf("%d%c",&s[i].id,&c);
            if(c == 'm')
            {
                s[i].ty = 1;
            }
            else if(c == 's')
            {
                s[i].ty = 2;
            }
            else if(c == 'p')
            {
                s[i].ty = 3;
            }
            else if(c == 'c')
            {
                s[i].ty = 4;
            }
        }

        for(i = 1;i <= 9; ++i)
        {
            s[14].id = i;
            s[14].ty = 1;
            if(Is_Win(s))
            {
                temp.id = i;
                temp.ty = 'm';
               st[top++] = temp;
            }
        }

        for(i = 1;i <= 9; ++i)
        {
            s[14].id = i;
            s[14].ty = 2;
            if(Is_Win(s))
            {
                temp.id = i;
                temp.ty = 's';
                st[top++] = temp;
            }
        }

        for(i = 1;i <= 9; ++i)
        {
            s[14].id = i;
            s[14].ty = 3;
            if(Is_Win(s))
            {
                temp.id = i;
                temp.ty = 'p';
                st[top++] = temp;
            }
        }

        for(i = 1;i <= 7; ++i)
        {
            s[14].id = i;
            s[14].ty = 4;
            if(Is_Win(s))
            {
                temp.id = i;
                temp.ty = 'c';
                st[top++] = temp;
            }
        }

        if(top == 0)
        {
            printf("Nooten\n");
        }
        else
        {
            printf("%d",top);
            for(i = 0;i < top; ++i)
            {
                printf(" %d%c",st[i].id,st[i].ty);
            }
            printf("\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值