原题传送门

首先先要学会麻将,然后会发现就是一个暴力dp,分三种情况考虑:

1.非七对子国士无双,设\(dp_{i,j,k,a,b}\)表示看到了第\(i\)种牌,一共有\(j\)个\(i-1\)开头的顺子,有\(k\)个\(i\)开头的顺子,有\(a\)个面子/杠子,有\(b\)个雀头时最大分数,暴力转移即可

2.七对子,设\(dp_{i,j}\)表示看到了第\(i\)种牌,一共有\(j\)个雀头时最大分数,暴力转移即可

3.国士无双,设\(dp_{i,j}\)表示看到了国士无双限定的第\(i\)张牌,已经选了\(j\)张牌时最大分数,暴力转移即可

最后比个最大就星了

#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline void write(register ll x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
int T,v,cnt[35],mrk[35];
ll C[5][5]={
{1,0,0,0,0},{1,1,0,0,0},{1,2,1,0,0},{1,3,3,1,0},{1,4,6,4,1}
};
ll bin[5]={1,2,4,8,16};
inline void upd(register ll &x,register ll y)
{
x=x>y?x:y;
}
inline ll chose(register int x,register int y)
{
return C[cnt[x]][y]*(mrk[x]?bin[y]:1);
}
inline ll work1()
{
static ll dp[35][3][3][5][2];
memset(dp,0,sizeof(dp));
dp[0][0][0][0][0]=1;
for(register int i=0;i<34;++i)
for(register int j=0;j<3;++j)
if(!j||i>7&&(i-7)%9!=0&&(i-7)%9!=1)
for(register int k=0;k<3;++k)
if(!k||i>7&&(i-7)%9!=8&&(i-7)%9!=0)
if(cnt[i+1]>=j+k)
for(register int a=j+k;a<=4;++a)
for(register int b=0;b<=1;++b)
if(dp[i][j][k][a][b])
{
for(register int c=0;c<=2&&j+k+c<=cnt[i+1]&&a+c<=4;++c)
for(register int d=0;j+k+c+d*3<=cnt[i+1]&&a+c+d<=4;++d)
{
int t=j+k+c+d*3;
upd(dp[i+1][k][c][a+c+d][b],dp[i][j][k][a][b]*chose(i+1,t));
if(!b&&t+2<=cnt[i+1])
upd(dp[i+1][k][c][a+c+d][1],dp[i][j][k][a][b]*chose(i+1,t+2));
}
if(cnt[i+1]-j-k==4&&a<4)
upd(dp[i+1][k][0][a+1][b],dp[i][j][k][a][b]*chose(i+1,4));
}
return dp[34][0][0][4][1];
}
inline ll work2()
{
static ll dp[35][8];
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(register int i=0;i<34;++i)
for(register int j=0;j<=7;++j)
{
upd(dp[i+1][j],dp[i][j]);
if(j<7)
upd(dp[i+1][j+1],dp[i][j]*chose(i+1,2));
}
return dp[34][7]*7;
}
int id[]={0,1,2,3,4,5,6,7,8,16,17,25,26,34};
inline ll work3()
{
static ll dp[14][15];
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(register int i=0;i<13;++i)
for(register int j=0;j<=14;++j)
for(register int k=1;k<=cnt[id[i+1]]&&k<=2;++k)
upd(dp[i+1][j+k],dp[i][j]*chose(id[i+1],k));
return dp[13][14]*13;
}
inline int read()
{
int v;
char str[5];
scanf("%s",str);
if(str[0]=='0')
return 0;
if(strlen(str)==1)
{
if(str[0]=='E')
v=1;
else if(str[0]=='S')
v=2;
else if(str[0]=='W')
v=3;
else if(str[0]=='N')
v=4;
else if(str[0]=='Z')
v=5;
else if(str[0]=='B')
v=6;
else
v=7;
}
else
{
if(str[1]=='m')
v=7;
else if(str[1]=='p')
v=16;
else
v=25;
v+=str[0]-'0';
}
return v;
}
int main()
{
scanf("%d",&T);
while(T--)
{
for(register int i=1;i<=34;++i)
cnt[i]=4,mrk[i]=0;
while(v=read())
--cnt[v];
while(v=read())
mrk[v]=1;
write(max(work1(),max(work2(),work3()))),puts("");
}
return 0;
}

【题解】Luogu P5301 [GXOI/GZOI2019]宝牌一大堆的更多相关文章

  1. luogu P5301 [GXOI/GZOI2019]宝牌一大堆

    传送门 wdnm又是打麻将 首先国土无双可以直接枚举哪种牌用了\(2\)次算贡献,然后\(7\)个对子可以把每种牌的对子贡献排序,取最大的\(7\)个,剩下的牌直接暴力枚举是不行的,考虑dp,设\(f ...

  2. P5301 [GXOI/GZOI2019]宝牌一大堆

    题目地址:P5301 [GXOI/GZOI2019]宝牌一大堆 这里是官方题解(by lydrainbowcat) 部分分 直接搜索可以得到暴力分,因为所有和牌方案一共只有一千万左右,稍微优化一下数据 ...

  3. 【BZOJ5503】[GXOI/GZOI2019]宝牌一大堆(动态规划)

    [BZOJ5503][GXOI/GZOI2019]宝牌一大堆(动态规划) 题面 BZOJ 洛谷 题解 首先特殊牌型直接特判. 然后剩下的部分可以直接\(dp\),直接把所有可以存的全部带进去大力\(d ...

  4. [LOJ3084][GXOI/GZOI2019]宝牌一大堆——DP

    题目链接: [GXOI/GZOI2019]宝牌一大堆 求最大值容易想到$DP$,但如果将$7$种和牌都考虑进来的话,$DP$状态不好设,我们将比较特殊的七小对和国士无双单独求,其他的进行$DP$. 观 ...

  5. [GXOI/GZOI2019]宝牌一大堆(dp)

    luogu     bzoj 这个麻将题还算挺友善的,比隔壁zjoi的要好得多... 比较正常的做法是五维dp 但事实上六维dp也是完全不会被卡的 七对子选权值最高的七个,国士无双直接$13^2$暴力 ...

  6. 题解 P5301 【[GXOI/GZOI2019]宝牌一大堆】

    这道题除了非常恶心以外也没有什么非常让人恶心的地方 当然一定要说有的话还是有的,就是这题和咱 ZJOI 的 mahjong 真的是好像的说~ 于是就想说这道题出题人应该被 锕 掉 noteskey 整 ...

  7. [luogu 5301][bzoj 5503] [GXOI/GZOI2019] 宝牌一大堆

    题面 好像ZJOI也考了一道麻将, 这是要发扬中华民族的赌博传统吗??? 暴搜都不会打, 看到题目就自闭了, 考完出来之后看题解, \(dp\), 可惜自己想不出来... 对于国士无双(脑子中闪过了韩 ...

  8. [GXOI/GZOI2019]宝牌一大堆

    感觉比ZJOI的麻将要休闲很多啊. 这个题就是一个最优化问题,没有面子的特殊牌型可以直接用复杂度较低的贪心判掉. 有面子的话就是一个经典dp.(曾经还在ZJOI写过这个毒瘤东西 大概就是存一下对子,面 ...

  9. [GX/GZOI2019]宝牌一大堆(DP)

    出这种麻将题有意思吗? 乍看很难实则很水,就是麻将式DP,想必大家很熟悉了吧.首先把“国士无双”和“七对子”两种牌型判掉,然后观察牌胡的形式,发现每多一张牌实际上就是把1个面子变成1个杠子,然后可以直 ...

随机推荐

  1. CTF-代码审计(1)——parse_str()变量覆盖

    题目连接:http://222.18.158.226:7000/iscc.php 考点:parse_str()变量覆盖 代码: PHP知识点: 1.parse_url() 参照网址:https://w ...

  2. linux echo命令颜色显示

    echo命令颜色显示: echo:      -n:  不换行.      -e:让转移符生效. \t(tab) \n (换行) 实例: $ echo -e "\033[34mabcd\03 ...

  3. Linux shell 函数应用示例01

    函数Function的使用 定义函数 (1) 函数名称() {     ...     ... } (2) function 函数名称{     ...     ... } 调用函数         ...

  4. Linux shell while循环语句

    for :明确循环次数 while :不确定循环换次数 while循环 (1) while CONDITION:do       statement       statement       < ...

  5. 【IOS】libimobiledevice常用命令

    libimobiledevice 是一个跨平台的软件库,支持 iPhone®, iPod Touch®, iPad® and Apple TV® 等设备的通讯协议.   安装 命令: brew ins ...

  6. CodeForces 150E: Freezing with Style

    题目传送门:CF150E. 据说这个傻逼题还有一个 \(\log\) 的做法,但是我还不会. 题意简述: 给定一棵 \(n\)(\(2\le n\le 10^5\))个点的树,边有边权. 定义一条路径 ...

  7. GitHub的SSH key配置以及常用的git命令介绍

    一. GitHub的SSH key配置 (以windows为例,Mac iOS系统类似) SSH Key 是一种方法来确定受信任的计算机,从而实现免密码登录.Git是分布式的代码管理工具,远程的代码管 ...

  8. Java 为什么需要包装类,如何使用包装类?

    出处:https://cloud.tencent.com/developer/article/1362754

  9. LoadRunner开发http协议接口之form表单脚本

    loadrunner传form表单,用web_submit_data函数. Action() { // lr_start_transaction("hp_homepage"); / ...

  10. CentOS7 最小安装 vmware 创建虚拟机 nmcli ip systemctl

    镜像网站 一些开源软件的国内镜像源 站点版 (一).企业站 1.搜狐:http://mirrors.sohu.com/ 2.网易:http://mirrors.163.com/ 3.阿里云:http: ...