简单的一处题解记录操作疑问
查看原帖
简单的一处题解记录操作疑问
549521
boy♂Next♂dooor楼主2024/10/5 16:47

题解代码来自大佬博客https://www.cnblogs.com/Xing-Ling/p/11673395.html

疑问处于dfs里面的注释中

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define Re register int
using namespace std;
int n,x,y,T,ans,gs[20];
inline void in(Re &x){
    int f=0;x=0;char c=getchar();
    while(c<'0'||c>'9')f|=c=='-',c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x=f?-x:x;
}
inline void dfs(Re g){
    Re p4=0,p3=0,p2=0,p1=0;
    for(Re i=1;i<=14;++i){//扫描3~king (1~14)
    	if(gs[i]==1)++p1;//单牌
    	if(gs[i]==2)++p2;//双牌
    }
    for(Re i=1;i<=14;++i)//扫描3~king
    	if(gs[i]==4){//4牌
            ++p4;//不管带不带.这个四牌肯定要出 
            if(p1>=2){p1-=2;continue;}//带两个单牌
            if(p2>=2){p2-=2;continue;}//带两个双牌
       //这里疑问:带了两个双牌p2-2,为什么单排不会多两张p1+2呢?
            if(p2>=1){p2-=1;continue;}//带一个双牌(两个一样的单牌)
            //一个四牌(炸弹)
    	}
    for(Re i=1;i<=14;++i)//扫描3~king (1~14)
    	if(gs[i]==3){//3牌
            ++p3;//不管带不带,这个三牌肯定要出 
            if(p1>=1){p1-=1;continue;}//带一个单牌
            if(p2>=1){p2-=1;continue;}//带一个双牌
            //一个三牌
    	}
    ans=min(ans,g+p1+p2+p3+p4);//没有顺子的最小答案
    for(Re i=1,j;i<=8;++i){//单顺子,最大为(10~A)8~12 
    	for(j=i;j<=12;++j){
            gs[j]-=1;//反正最后要回溯,先减了再说
            if(gs[j]<0)break;//无法继续连下去了,退出
            if(j-i+1>=5)dfs(g+1);//单顺子长度至少为5
    	}
    	if(j==13)--j;//如果全部连完了,2(13)是不用回溯的
    	while(j>=i)gs[j]+=1,--j;//最后放在一起回溯
    }
    for(Re i=1,j;i<=10;++i){//双顺子,最大为Q~A(10~12)
    	for(j=i;j<=12;++j){
            gs[j]-=2;
            if(gs[j]<0)break;
            if(j-i+1>=3)dfs(g+1);//双顺子长度至少为3
    	}
    	if(j==13)--j;
    	while(j>=i)gs[j]+=2,--j;
    }
    for(Re i=1,j;i<=11;++i){//三顺子,最大为Q~A(10~12) 
    	for(j=i;j<=12;++j){
            gs[j]-=3;
            if(gs[j]<0)break;
            if(j-i+1>=2)dfs(g+1);//三顺子长度至少为2
    	}
    	if(j==13)--j;
    	while(j>=i)gs[j]+=3,--j;
    }
}
int main(){
//  freopen("landlords.in","r",stdin);
//  freopen("landlords.out","w",stdout);
    in(T),in(n);
    while(T--){
    	memset(gs,0,sizeof(gs));
    	for(Re i=1;i<=n;++i){
            in(x),in(y);
            if(x==0)++gs[14];//14:  大王
            if(x==2)++gs[13];//13:   2
            if(x==1)++gs[12];//12:   A
            if(x>=3)++gs[x-2];//x-2: x
            // J: 11-2=9
            // Q: 12-2=10
            // K: 13-2=11
    	}
    	ans=2e9,dfs(0);
    	printf("%d\n",ans);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

2024/10/5 16:47
加载中...