jzoj 4833. 【NOIP2016提高A组集训第3场10.31】Mahjong dfs+暴力

来源:互联网 发布:淘宝上好的cos店 编辑:程序博客网 时间:2024/05/16 15:53

题意

有27种牌,分别为1s到9s,1w到9w,1p到9p,每种牌有四张。现在给出一副牌(13张),求去掉哪一张牌后可以听得牌数最多。
定义一副牌为胡牌,则这副牌必须满足由4个句子和一副将牌组成。句子可以是三只完全一样的牌,也可以是三只种类相同数字连续的牌,比如说1s,2s,3s。将牌则必须是两只完全相同的牌。
定义一副牌(只有13张)的听牌为再加上这张牌就可以成为胡牌。
样例:
输入1:
1s 2s 3s 4s 6s 6s 6s 2w 2w 2w 3p 3p 7p 7p
输入2:
1s 1s 1s 2s 3s 4s 5s 6s 6p 6p 7p 8p 8p 9p
输出1:
1 4
输出2:
12 10

分析

看到这题每个人肯定都想起了noip2015d1t3斗地主。这题曾经是多少人的噩梦啊!
这题其实也跟斗地主差不多,都是无脑暴力求解。
枚举删掉哪一个然后再枚举每个牌看看能不能听就好了。
嘴巴AC十分简单,但打起来就是另一回事了。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;int use[4][20];struct data{int num,op,s,id;}a[20],b[20],c[20];bool cmp(data a,data b){    return a.op<b.op||a.op==b.op&&a.num<b.num;}bool check(int x,int y,int jiang){    if (x>y)    {        if (jiang) return 1;        else return 0;    }    if (!c[x].s) return check(x+1,y,jiang);    if (c[x].s==1)    {        if (c[x+1].op==c[x].op&&c[x+1].num==c[x].num+1&&c[x+1].s&&c[x+2].op==c[x].op&&c[x+2].num==c[x].num+2&&c[x+2].s&&x+2<=y)        {            c[x].s--;c[x+1].s--;c[x+2].s--;            if (check(x+1,y,jiang)) return 1;            c[x].s++;c[x+1].s++;c[x+2].s++;        }    }else if (c[x].s==2)    {        if (!jiang)            if (check(x+1,y,1)) return 1;        if (c[x+1].op==c[x].op&&c[x+1].num==c[x].num+1&&c[x+1].s>1&&c[x+2].op==c[x].op&&c[x+2].num==c[x].num+2&&c[x+2].s>1&&x+2<=y)        {            c[x].s-=2;c[x+1].s-=2;c[x+2].s-=2;            if (check(x+1,y,jiang)) return 1;            c[x].s+=2;c[x+1].s+=2;c[x+2].s+=2;        }    }else if (c[x].s==3)    {        if (!jiang)        {            c[x].s-=2;            if (check(x,y,1)) return 1;            c[x].s+=2;        }        if (check(x+1,y,jiang)) return 1;    }else    {        if (!jiang)        {            c[x].s-=2;            if (check(x,y,1)) return 1;            c[x].s+=2;        }        c[x].s-=3;        if (check(x,y,jiang)) return 1;        c[x].s+=3;        if (c[x+1].op==c[x].op&&c[x+1].num==c[x].num+1&&c[x+1].s>3&&c[x+2].op==c[x].op&&c[x+2].num==c[x].num+2&&c[x+2].s>3&&x+2<=y)        {            c[x].s-=2;c[x+1].s-=2;c[x+2].s-=2;            if (check(x+1,y,jiang)) return 1;            c[x].s+=2;c[x+1].s+=2;c[x+2].s+=2;        }    }    return 0;}int find(int n,int x,int y){    memset(use,0,sizeof(use));    int ans=0;    for (int i=1;i<=n;i++)    {        if (!use[b[i].op][b[i].num])        use[b[i].op][b[i].num]=1;        for (int j=1;j<=n;j++)            c[j]=b[j];        c[i].s++;        if (ans<0) ans=0;        if (check(1,n,0)) ans=ans+4-b[i].s;        if (!use[b[i].op][b[i].num+1]&&(b[i+1].op!=b[i].op||b[i+1].num!=b[i].num+1)&&b[i].num+1<=9)        {            use[b[i].op][b[i].num+1]=1;            for (int j=1;j<=n;j++)                c[j]=b[j];            c[n+1].op=b[i].op;c[n+1].num=b[i].num+1;c[n+1].s=1;            sort(c+1,c+n+2,cmp);            if (check(1,n+1,0))             {                ans+=4;                if (b[i].op==x&&b[i].num+1==y) ans--;            }        }        if (!use[b[i].op][b[i].num-1]&&(b[i-1].op!=b[i].op||b[i-1].num!=b[i].num-1)&&b[i].num-1>0)        {            use[b[i].op][b[i].num-1]=1;            for (int j=1;j<=n;j++)                c[j]=b[j];            c[n+1].op=b[i].op;c[n+1].num=b[i].num-1;c[n+1].s=1;            sort(c+1,c+n+2,cmp);            if (check(1,n+1,0))             {                ans+=4;                if (b[i].op==x&&b[i].num-1==y) ans--;            }        }    }    return ans;}int main(){    //freopen("mahjong.in","r",stdin);    //freopen("mahjong.out","w",stdout);    for (int i=1;i<=14;i++)    {        char ch[3];        scanf("%s",ch);        if (ch[1]=='s') a[i].op=1;        else if (ch[1]=='w') a[i].op=2;        else a[i].op=3;        a[i].num=ch[0]-'0';        a[i].s=1;        a[i].id=i;    }    sort(a+1,a+15,cmp);    int n=14;    for (int i=1;i<=13;i++)        if (a[i].op==a[i+1].op&&a[i].num==a[i+1].num)        {            a[i].op=4;            n--;            a[i+1].s+=a[i].s;            a[i+1].id=min(a[i+1].id,a[i].id);        }    sort(a+1,a+15,cmp);    int ans=0,ansx=0;    for (int i=1;i<=n;i++)    {        for (int j=1;j<=n;j++)            b[j]=a[j];        b[i].s--;        int m=n;        if (b[i].s==0)        {            b[i].op=4;            m--;            sort(b+1,b+n+1,cmp);        }        int w=find(m,a[i].op,a[i].num);        if (w>ans)        {            ans=w;            ansx=a[i].id;        }    }    printf("%d %d",ansx,ans);    return 0;}
0 0
原创粉丝点击