【jzoj4833】【Mahjong】【搜索】

16 篇文章 0 订阅

题目大意

这里写图片描述

解题思路

暴力,先考虑顺子,再考虑四带,三带,对子,单牌,加点最优性剪枝即可。

code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define LD double
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a>b)?b:a)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const inf=2147483647;
int const maxn=40;
int n,num[10],flag,aaa[10000],cnt;
struct rec{
    int a,b;
};
rec a[20],b[20],c[10][10];bool ok;
bool check(int pos){
    ok=1;cnt++;if(cnt>400000)return 0;
    fo(i,2,num[pos])
        if(c[pos][i].b!=c[pos][1].b){
            ok=0;
            break;
        }
    if(!ok)return ok;
    ok=1;
    fo(i,2,num[pos])
        if(c[pos][i].a!=c[pos][1].a){
            ok=0;
            break;
        }
    if(ok)return ok;
    if(num[pos]==1)return 1;
    else if(num[pos]==2)return (max((c[pos][1].a-c[pos][2].a),-(c[pos][1].a-c[pos][2].a))<=2)&&(max((c[pos][1].a-c[pos][2].a),-(c[pos][1].a-c[pos][2].a))>=1);
    return ((max(c[pos][1].a,max(c[pos][2].a,c[pos][3].a))-min(c[pos][1].a,min(c[pos][2].a,c[pos][3].a))==2)&&(c[pos][1].a!=c[pos][2].a)&&(c[pos][1].a!=c[pos][3].a)&&(c[pos][3].a!=c[pos][2].a));
}
void dfs(int pos){
    if(pos>14){
        flag=1;
        return;
    }
    if(num[1]<2){
        ++num[1];
        c[1][num[1]].a=b[pos].a;
        c[1][num[1]].b=b[pos].b;
        if((num[1]==1)||((num[1]==2)&&(c[1][1].a==c[1][2].a)&&(c[1][1].b==c[1][2].b)))dfs(pos+1);
        num[1]--;
    }
    fo(i,2,5)
        if(num[i]<3){
            ++num[i];
            c[i][num[i]].a=b[pos].a;
            c[i][num[i]].b=b[pos].b;
            if(check(i))dfs(pos+1);
            num[i]--;
        }
}
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    fo(i,1,14){
        char c1,c2;scanf("%c%c ",&c1,&c2);
        a[i].a=c1-'0';a[i].b=c2;aaa[c2]++;
    }
    int ans1=0,ans2=0;
    fo(i,1,14){
        int sum=0,tmp;
        fo(j,1,9){
            fo(k,1,14)
                if(i!=k){
                    b[k].a=a[k].a;
                    b[k].b=a[k].b;
                }else{
                    b[k].a=j;
                    b[k].b='w';
                }
            tmp=0;
            fo(k,1,14)
                if((a[k].a==j)&&(a[k].b=='w'))tmp++;
            flag=0;
            fo(k,1,5)num[k]=0;cnt=0;
            if((tmp!=4)&&(aaa['w']>0)&&(!((b[i].a==a[i].a)&&(b[i].b==a[i].b))))dfs(1);
            if(flag)sum+=4-tmp;
            fo(k,1,14)
                if(i!=k){
                    b[k].a=a[k].a;
                    b[k].b=a[k].b;
                }else{
                    b[k].a=j;
                    b[k].b='p';
                }
            tmp=0;
            fo(k,1,14)
                if((a[k].a==j)&&(a[k].b=='p'))tmp++;
            flag=0;
            fo(k,1,5)num[k]=0;cnt=0;
            if((tmp!=4)&&(aaa['p']>0)&&(!((b[i].a==a[i].a)&&(b[i].b==a[i].b))))dfs(1);
            if(flag)sum+=4-tmp;
            fo(k,1,14)
                if(i!=k){
                    b[k].a=a[k].a;
                    b[k].b=a[k].b;
                }else{
                    b[k].a=j;
                    b[k].b='s';
                }
            tmp=0;
            fo(k,1,14)
                if((a[k].a==j)&&(a[k].b=='s'))tmp++;
            flag=0;
            fo(k,1,5)num[k]=0;cnt=0;
            if((tmp!=4)&&(aaa['s']>0)&&(!((b[i].a==a[i].a)&&(b[i].b==a[i].b))))dfs(1);
            if(flag)sum+=4-tmp;
        }
        if(sum>ans2){
            ans1=i;
            ans2=sum;
        }
    }
    printf("%d %d",ans1,ans2);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值