【题解】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个杠子,然后可以直 ...
随机推荐
- 在dockers中调试dump的dotnet程序
其他调试参考文章 centos7使用lldb调试netcore应用转储dump文件 centos7 lldb 调试netcore应用的内存泄漏和死循环示例(dump文件调试) 生成dump文件 如何在 ...
- Modern Cpp记录
#include <iostream> # include <set> #include <chrono> #ifndef UNUSED #define UNUSE ...
- NPOI.dll 在哪里?
一.问题 NPOI下载后找不到网上人家说的几个DLL https://bbs.csdn.net/topics/392510552 二.答案: 1.VS2015引用NPOI2.4.1和NuGet的安装方 ...
- 华为企业级AS111-S,比较垃圾的地方
今天换了一个华为企业级AS111-S 路由器,比较垃圾的地方: 1. 网页管理界面是https,却用一个无效的证书,chrome直接不能访问,IE可以访问,但第一次登陆改密码的时候就出错了. 然后怎么 ...
- 团队第五次——Alpha2的发布
这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/2019autumnsystemanalysisanddesign/ 这个作业要求在哪里 https:// ...
- 数据结构篇——字典树(trie树)
引入 现在有这样一个问题, 给出\(n\)个单词和\(m\)个询问,每次询问一个单词,回答这个单词是否在单词表中出现过. 好像还行,用 map<string,bool> ,几行就完事了. ...
- 洛谷P2365 任务安排(斜率优化dp)
传送门 思路: 最朴素的dp式子很好考虑:设\(dp(i,j)\)表示前\(i\)个任务,共\(j\)批的最小代价. 那么转移方程就有: \[ dp(i,j)=min\{dp(k,j-1)+(sumT ...
- RF元素定位的例子
Execute Javascript $("input[type='button']").click() Comment Click Button css=input.login_ ...
- Python实战之ATM+购物车
ATM + 购物车 需求分析 ''' - 额度 15000或自定义 - 实现购物商城,买东西加入 购物车,调用信用卡接口结账 - 可以提现,手续费5% - 支持多账户登录 - 支持账户间转账 - 记录 ...
- selenium webdriver使用的一些小技巧(持续更新中)
1.开始结束时间只支持控件选择,不支持填写,怎么办? 如下图: 解决方案: 用javaScipt把开始结束时间的reaonly属性去除,然后再输入,举例如下 /** * 输入开始日期 ...