欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

斗地主

程序员文章站 2022-06-12 13:38:29
...

斗地主
斗地主
斗地主

  • 当初看到这道题,我就有点懵,这个题目这么长,除了直接强行搜索想不出任何办法,那就搜吧,结果没想到就这样过了
  • 其实思路比较简单:
    • ①花色不影响大小,那么花色可以不管
    • ②我们可以发现只有顺子中会出现2点和大小王,那么我们在搜索时就可以先不管顺子,先把其他的解决
    • ③顺子因为较长可以作为后续优化处理,当发现还剩牌时步数已经比答案多,则返回
      下面是代码:
//landlords
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int t,n,ans;
int a[25],c[25];
int rest(){
    memset(c,0,sizeof(c));
    for(int i=0;i<=13;i++)c[a[i]]++;
    int tot=0;
    while(c[4]&&c[2]>1){    //4带2带2
        c[4]--;
        c[2]-=2;
        tot++;
    }
    while(c[4]&&c[1]>1){     //4带1带1
        c[4]--;
        c[1]-=2;
        tot++;
    }
    while(c[4]&&c[2]){     //4带2
        c[4]--;
        c[2]--;
        tot++;
    }
    while(c[3]&&c[2]){    //3带2
        c[3]--;
        c[2]--;
        tot++;
    }
    while(c[3]&&c[1]){    //3带1
        c[3]--;
        c[1]--;
        tot++;
    }
    return tot+c[1]+c[2]+c[3]+c[4];   //剩下没有出完的只能单出
}
void dfs(int now){
    if(now>=ans) return;
    int tmp=rest();
    if(now+tmp<ans)
        ans=now+tmp;
    for(int i=2;i<=13;i++){   //3顺子
        int j=i;
        while(a[j]>=3) j++;
        if(j-i>=2){
            for(int k=i+1;k<=j-1;k++){
                for(int l=i;l<=k;l++)
                    a[l]-=3;
                dfs(now+1);
                for(int l=i;l<=k;l++)
                    a[l]+=3;
            }
        }
    }
    for(int i=2;i<=13;i++){     //双顺子
        int j=i;
        while(a[j]>=2) j++;
        if(j-i>=3){
            for(int k=i+2;k<=j-1;k++){
                for(int l=i;l<=k;l++)
                    a[l]-=2;
                dfs(now+1);
                for(int l=i;l<=k;l++)
                    a[l]+=2;
            }
        }
    }
    for(int i=2;i<=13;i++){    //单顺子
        int j=i;
        while(a[j]>=1) j++;
        if(j-i>=5){
            for(int k=i+4;k<=j-1;k++){
                for(int l=i;l<=k;l++)
                    a[l]-=1;
                dfs(now+1);
                for(int l=i;l<=k;l++)
                    a[l]+=1;
            }
        }
    }
}
int main()
{
//  freopen("landlords.in","r",stdin);
//  freopen("landlords.out","w",stdout);
    scanf("%d%d",&t,&n);
    while(t--){
        memset(a,0,sizeof(a));
        int x,y;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            if(x==1) x=13;        //处理A点,只要保证大小顺序即可
            else if(x) x--;
            a[x]++;
        }
        ans=1e9;
        dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}
相关标签: NOIP