【题解】Luogu P5301 [GXOI/GZOI2019]宝牌一大堆
原题传送门
首先先要学会麻将,然后会发现就是一个暴力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]宝牌一大堆的更多相关文章
- luogu P5301 [GXOI/GZOI2019]宝牌一大堆
传送门 wdnm又是打麻将 首先国土无双可以直接枚举哪种牌用了\(2\)次算贡献,然后\(7\)个对子可以把每种牌的对子贡献排序,取最大的\(7\)个,剩下的牌直接暴力枚举是不行的,考虑dp,设\(f ...
- P5301 [GXOI/GZOI2019]宝牌一大堆
题目地址:P5301 [GXOI/GZOI2019]宝牌一大堆 这里是官方题解(by lydrainbowcat) 部分分 直接搜索可以得到暴力分,因为所有和牌方案一共只有一千万左右,稍微优化一下数据 ...
- 【BZOJ5503】[GXOI/GZOI2019]宝牌一大堆(动态规划)
[BZOJ5503][GXOI/GZOI2019]宝牌一大堆(动态规划) 题面 BZOJ 洛谷 题解 首先特殊牌型直接特判. 然后剩下的部分可以直接\(dp\),直接把所有可以存的全部带进去大力\(d ...
- [LOJ3084][GXOI/GZOI2019]宝牌一大堆——DP
题目链接: [GXOI/GZOI2019]宝牌一大堆 求最大值容易想到$DP$,但如果将$7$种和牌都考虑进来的话,$DP$状态不好设,我们将比较特殊的七小对和国士无双单独求,其他的进行$DP$. 观 ...
- [GXOI/GZOI2019]宝牌一大堆(dp)
luogu bzoj 这个麻将题还算挺友善的,比隔壁zjoi的要好得多... 比较正常的做法是五维dp 但事实上六维dp也是完全不会被卡的 七对子选权值最高的七个,国士无双直接$13^2$暴力 ...
- 题解 P5301 【[GXOI/GZOI2019]宝牌一大堆】
这道题除了非常恶心以外也没有什么非常让人恶心的地方 当然一定要说有的话还是有的,就是这题和咱 ZJOI 的 mahjong 真的是好像的说~ 于是就想说这道题出题人应该被 锕 掉 noteskey 整 ...
- [luogu 5301][bzoj 5503] [GXOI/GZOI2019] 宝牌一大堆
题面 好像ZJOI也考了一道麻将, 这是要发扬中华民族的赌博传统吗??? 暴搜都不会打, 看到题目就自闭了, 考完出来之后看题解, \(dp\), 可惜自己想不出来... 对于国士无双(脑子中闪过了韩 ...
- [GXOI/GZOI2019]宝牌一大堆
感觉比ZJOI的麻将要休闲很多啊. 这个题就是一个最优化问题,没有面子的特殊牌型可以直接用复杂度较低的贪心判掉. 有面子的话就是一个经典dp.(曾经还在ZJOI写过这个毒瘤东西 大概就是存一下对子,面 ...
- [GX/GZOI2019]宝牌一大堆(DP)
出这种麻将题有意思吗? 乍看很难实则很水,就是麻将式DP,想必大家很熟悉了吧.首先把“国士无双”和“七对子”两种牌型判掉,然后观察牌胡的形式,发现每多一张牌实际上就是把1个面子变成1个杠子,然后可以直 ...
随机推荐
- c#导出数据到csv文本文档中,数据前面的0不见了解决方法
((char)(9)).ToString() + dataRow["FUserName"].ToString().Trim() + "\t",
- OKGo vs RxHttpUtils ...
jeasonlzy/okhttp-OkGohttps://github.com/jeasonlzy/okhttp-OkGo Android OkGo基本操作https://www.jianshu.co ...
- NI CWGraph 显示波形图
ptrWaveBox.Axes(1).Maximum = 1000 ptrWaveBox.Axes(2).Maximum = 20 ptrWaveBox.Axes(2).Minimum = 0 Dim ...
- 重新编译kubeadm,修改默认证书时间
参考 kubeadm alpha certs renew Kubeadm1.14 证书调整 kubeadm 部署的 kubernetes 集群,默认的证书有效时间是1年,需要每年手工更新. 1. 重新 ...
- LOJ 3120: 洛谷 P5401: 「CTS2019 | CTSC2019」珍珠
题目传送门:LOJ #3120. 题意简述: 称一个长度为 \(n\),元素取值为 \([1,D]\) 的整数序列是合法的,当且仅当其中能够选出至少 \(m\) 对相同元素(不能重复选出元素). 问合 ...
- (HK1-1)海康网络摄像机的使用
https://blog.csdn.net/u014552102/article/details/86700057 一.手机客户端操作: 首先在莹石商城官网https://www.ys7.com/下 ...
- ubunt 文件permission denied问题的解决
在linux系统使用过程中,升级python到3.6以后,执行pip命令,遇到permission denied问题,系统显示如下: -bash: /home/www/my_flask/venv/bi ...
- 协程,yield,i多路复用,复习
课程回顾: 线程池 队列:同一进程内的队列 先进先出 后进先出 优先级队列 线程池中的回调函数是谁在调用? 线程池中的回调函数是子线程调用的,和父线程没有关系 进程池中的会点函数是父进程调用的,和子进 ...
- Codeforces Round #603 (Div. 2) E - Editor(线段树,括号序列)
- 使用mxnet实现卷积神经网络LeNet
1.LeNet模型 LeNet是一个早期用来识别手写数字的卷积神经网络,这个名字来源于LeNet论文的第一作者Yann LeCun.LeNet展示了通过梯度下降训练卷积神经网络可以达到手写数字识别在当 ...