zoukankan      html  css  js  c++  java
  • 题解 P5301 【[GXOI/GZOI2019]宝牌一大堆】

    这道题除了非常恶心以外也没有什么非常让人恶心的地方

    当然一定要说有的话还是有的,就是这题和咱 ZJOI 的 mahjong 真的是好像的说~

    于是就想说这道题出题人应该被 锕 掉

    noteskey

    整体的思路就是特判国士无双和七对子,然后 dp 搞普通的胡牌

    dp 状态设计和楼上大佬说的一样,就是用一个五维的 (f[i][j][k][l][p]) 表示当前处理了前 i 种类型的牌,存在 j 个 面子/杠子 ,以 i-1 开头的顺子要选 k 个,以 i 开头的面子要选 l 个,以及当前是否有 雀头 (用 p 表示)

    然后转移就非常的暴力了,反正这里的数据范围也比较小,枚举下状态转移就好了

    总的来说就是道 语文 + 码农 + dp 题,虽说没什么思维难度但我不见得能想出来

    watch out

    这题的字符串读入还是比较毒瘤的...要稍微注意一下不然可能会出事

    code

    这压行是同样的味道呢~

    //by Judge
    #include<bits/stdc++.h>
    #define Rg register
    #define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
    #define ll long long
    using namespace std;
    #ifndef Judge
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    #endif
    char buf[1<<21],*p1=buf,*p2=buf;
    inline bool cmax(ll& a,ll b){return a<b?a=b,1:0;}
    inline int read(){ int x=0,f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
    } inline void reads(string& s){ char c=getchar();
    	for(;!isalpha(c)&&!isdigit(c);c=getchar()); s="";
    	for(;isalpha(c)||isdigit(c);c=getchar()) s+=c;
    } char sr[1<<21],z[20];int CCF=-1,Z;
    inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
    inline void print(ll x,char chr='
    '){
    	if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
    	while(z[++Z]=x%10+48,x/=10);
    	while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
    } int t,cnt,a[41],b[41],C[5][5]; ll f[41][5][3][3][2],tp[41];
    int gs[14]={0,1,9,10,18,19,27,28,29,30,31,32,33,34}; string c;
    inline int id(){ if(c[0]=='B') return 34;
    	if(c[0]=='E') return 28; if(c[0]=='S') return 29; if(c[0]=='W') return 30;
    	if(c[0]=='N') return 31; if(c[0]=='Z') return 32; if(c[0]=='F') return 33;
    	if(c[1]=='m') return c[0]-48; if(c[1]=='p') return c[0]-39; return c[0]-30;
    }
    int main(){ C[0][0]=1;
    	fp(i,1,4){ C[i][0]=1;
    		fp(j,1,i) C[i][j]=C[i-1][j-1]+C[i-1][j];
    	}
    	fp(T,1,read()){
    		memset(a,0,sizeof a);
    		memset(b,0,sizeof b);
    		memset(f,0,sizeof f);
    		while(1){ reads(c);
    			if(c[0]=='0') break;
    			else ++a[id()];
    		}
    		while(1){ reads(c);
    			if(c[0]=='0') break;
    			else b[id()]=1;
    		}
    		fp(i,1,34) a[i]=4-a[i];
    		ll ans=0;
    		fp(i,1,13){ ll tmp=1; //枚举出现两次的牌 
    			fp(j,1,13) //枚举 13 种牌 
    				if(i==j)
    					if(a[gs[j]]<2) tmp=0; //如果数量不够就让 tmp=0 
    					else tmp*=C[a[gs[j]]][2]*(b[gs[j]]?4:1); //否则加贡献 
    				else
    					if(a[gs[j]]<1) tmp=0;
    					else tmp*=C[a[gs[j]]][1]*(b[gs[j]]?2:1);
    			cmax(ans,tmp*13);
    		}
    		cnt=0;
    		fp(i,1,34) if(a[i]>=2) tp[++cnt]=C[a[i]][2]*(b[i]?4:1);
    		if(cnt>=7){ //如果牌数大于等于 2 的不止 7 张就可以构成七对子 
    			sort(tp+1,tp+1+cnt); ll tmp=1; //选出权最大的 7 种牌 
    			fp(i,cnt-6,cnt) tmp*=tp[i]; //累乘贡献 
    			cmax(ans,tmp*7);
    		}
    		f[0][0][0][0][0]=1; //初始化边界 
    		fp(i,0,33) fp(j,0,4) for(Rg int k=0;k<3&&j+k<=4;++k){
    			if(k>=1&&(i==9||i==18||i>=27)) break; //不合法开头无法构成顺子 
    			for(Rg int l=0;l<3&&j+k+l<=4;++l){
    				if(l>=1&&(i==9||i==18||i==27)) break;
    				if(f[i][j][k][l][0]||f[i][j][k][l][1]) fp(u,k+l,a[i+1]){
    					ll tmp=C[a[i+1]][u]*(b[i+1]?(1<<u):1); //计算贡献 
    					// 四种转移 
    					if(j+u<=4&&u-k-l<3) 
    						cmax(f[i+1][j+k][l][u-k-l][0],f[i][j][k][l][0]*tmp),
    						cmax(f[i+1][j+k][l][u-k-l][1],f[i][j][k][l][1]*tmp);
    					if(u-k-l-2>=0&&j+u-2<=4)
    						cmax(f[i+1][j+k][l][u-k-l-2][1],f[i][j][k][l][0]*tmp);
    					if(u-k-l-3>=0&&j+u-2<=4)
    						cmax(f[i+1][j+k+1][l][u-k-l-3][0],f[i][j][k][l][0]*tmp),
    						cmax(f[i+1][j+k+1][l][u-k-l-3][1],f[i][j][k][l][1]*tmp);
    					if(u==4&&!k&&!l&&j<=3)
    						cmax(f[i+1][j+1][0][0][0],f[i][j][k][l][0]*tmp),
    						cmax(f[i+1][j+1][0][0][1],f[i][j][k][l][1]*tmp);
    				}
    			}
    		}
    		cmax(ans,f[34][4][0][0][1]),print(ans);
    	} return Ot(),0;
    }
    
  • 相关阅读:
    第三周学习笔记
    Python简易购物车程序
    记录回忆,谢谢你,别忘了我。
    学习第二周
    入园3个月首次写个帖
    Linux系统mysql多实例主从
    linux系统开机流程和启动nginx
    linux系统rsync命令
    linux监控进程状态命令自定义rpm包及kill命令
    linux搭建yum仓库
  • 原文地址:https://www.cnblogs.com/Judge/p/10749200.html
Copyright © 2011-2022 走看看