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

wdnm又是打麻将
首先国土无双可以直接枚举哪种牌用了\(2\)次算贡献,然后\(7\)个对子可以把每种牌的对子贡献排序,取最大的\(7\)个,剩下的牌直接暴力枚举是不行的,考虑dp,设\(f_{i,0\sim1,j,k,0\sim4,0\sim4}\),表示考虑前\(i\)种牌,\(0\sim1\)个对子,\(j\)个\(i-1,i,i+1\)顺子,\(k\)个\(i,i+1,i+2\)顺子,\(0\sim4\)个面子,\(0\sim4\)个杠子,的最大价值,转移枚举下一种牌\(i\)怎么放,可以放杠子,或者放\(i,i+1,i+2\)的顺子同时考虑放对子和刻子,然后最后用对应牌型的dp值更新答案
注意顺子的限制条件,同时建议限制一下状态中牌的总数不超过\(18\)个
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double
using namespace std;
const int N=40;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
map<string,int> id;
char cc[3];
void inii()
{
id["B"]=0;
id["1m"]=1;
id["2m"]=2;
id["3m"]=3;
id["4m"]=4;
id["5m"]=5;
id["6m"]=6;
id["7m"]=7;
id["8m"]=8;
id["9m"]=9;
id["1p"]=10;
id["2p"]=11;
id["3p"]=12;
id["4p"]=13;
id["5p"]=14;
id["6p"]=15;
id["7p"]=16;
id["8p"]=17;
id["9p"]=18;
id["1s"]=19;
id["2s"]=20;
id["3s"]=21;
id["4s"]=22;
id["5s"]=23;
id["6s"]=24;
id["7s"]=25;
id["8s"]=26;
id["9s"]=27;
id["E"]=28;
id["S"]=29;
id["W"]=30;
id["N"]=31;
id["Z"]=32;
id["F"]=33;
}
int c[5][5]={{1},{1,1},{1,2,1},{1,3,3,1},{1,4,6,4,1}},cn[N];
bool qb[N];
int gtws[13]={1,9,10,18,19,27,28,29,30,31,32,0,33};
LL f[2][2][3][3][5][5],qdz[N],ans;
int main()
{
inii();
int T=rd();
while(T--)
{
ans=0;
for(int i=0;i<34;++i) cn[i]=4,qb[i]=0;
while(1)
{
scanf("%s",cc);
if(cc[0]=='0') break;
--cn[id[cc]];
}
while(1)
{
scanf("%s",cc);
if(cc[0]=='0') break;
qb[id[cc]]=1;
}
bool fg=1;
for(int i=0;fg&&i<13;++i) fg=cn[gtws[i]];
if(fg)
{
LL sm=13;
for(int i=0;i<13;++i) sm*=(1ll<<qb[gtws[i]])*cn[gtws[i]];
for(int i=0;i<13;++i)
if(cn[gtws[i]]>=2) ans=max(ans,sm*(1ll<<qb[gtws[i]])*(cn[gtws[i]]-1)/2);
}
int m=0;
for(int i=0;i<34;++i)
if(cn[i]>=2) qdz[++m]=(1ll<<(qb[i]*2))*c[cn[i]][2];
if(m>=7)
{
sort(qdz+1,qdz+m+1);
LL sm=7;
for(int i=1;i<=7;++i) sm*=qdz[m-i+1];
ans=max(ans,sm);
}
memset(f,0,sizeof(f));
int nw=1,la=0;
f[la][0][0][0][0][0]=1;
for(int i=0;i<34;++i)
{
for(int j=0;j<=1;++j)
for(int k=0;k<=2;++k)
for(int l=0;l<=2;++l)
for(int p=0;p<=4&&j*2+p*3<=18;++p)
for(int q=0;q<=4&&j*2+p*3+q*4<=18;++q)
{
if(!f[la][j][k][l][p][q]) continue;
int res=cn[i]-k-l,lm=min(i>=1&&i<=27&&(i-1)%9+1<=7?2:0,res);
for(int o=0;o<=lm&&o<=cn[i+1]-l&&o<=cn[i+2]&&p+o<=4&&j*2+(p+o)*3+q*4<=18;++o)
{
LL dt=1ll<<(o*(qb[i]+qb[i+1]+qb[i+2]));
f[nw][j][l][o][p+o][q]=max(f[nw][j][l][o][p+o][q],f[la][j][k][l][p][q]*dt*c[cn[i]][o+k+l]);
if(o+2<=res&&!j&&(j+1)*2+(p+o)*3+q*4<=18) f[nw][j+1][l][o][p+o][q]=max(f[nw][j+1][l][o][p+o][q],f[la][j][k][l][p][q]*dt*c[cn[i]][o+k+l+2]*(1<<(qb[i]*2)));
if(o+3<=res&&p+o+1<=4&&j*2+(p+o+1)*3+q*4<=18) f[nw][j][l][o][p+o+1][q]=max(f[nw][j][l][o][p+o+1][q],f[la][j][k][l][p][q]*dt*c[cn[i]][o+k+l+3]*(1<<(qb[i]*3)));
}
if(res==4&&q+1<=4&&j*2+p*3+(q+1)*4<=18) f[nw][j][l][0][p][q+1]=max(f[nw][j][l][0][p][q+1],f[la][j][k][l][p][q]*c[cn[i]][4]*(1<<(qb[i]*4)));
f[la][j][k][l][p][q]=0;
}
nw^=1,la^=1;
}
ans=max(ans,f[la][1][0][0][4][0]);
ans=max(ans,f[la][1][0][0][3][1]);
ans=max(ans,f[la][1][0][0][2][2]);
ans=max(ans,f[la][1][0][0][1][3]);
ans=max(ans,f[la][1][0][0][0][4]);
printf("%lld\n",ans);
}
return 0;
}
luogu P5301 [GXOI/GZOI2019]宝牌一大堆的更多相关文章
- 【题解】Luogu P5301 [GXOI/GZOI2019]宝牌一大堆
原题传送门 首先先要学会麻将,然后会发现就是一个暴力dp,分三种情况考虑: 1.非七对子国士无双,设\(dp_{i,j,k,a,b}\)表示看到了第\(i\)种牌,一共有\(j\)个\(i-1\)开头 ...
- P5301 [GXOI/GZOI2019]宝牌一大堆
题目地址:P5301 [GXOI/GZOI2019]宝牌一大堆 这里是官方题解(by lydrainbowcat) 部分分 直接搜索可以得到暴力分,因为所有和牌方案一共只有一千万左右,稍微优化一下数据 ...
- [LOJ3084][GXOI/GZOI2019]宝牌一大堆——DP
题目链接: [GXOI/GZOI2019]宝牌一大堆 求最大值容易想到$DP$,但如果将$7$种和牌都考虑进来的话,$DP$状态不好设,我们将比较特殊的七小对和国士无双单独求,其他的进行$DP$. 观 ...
- 【BZOJ5503】[GXOI/GZOI2019]宝牌一大堆(动态规划)
[BZOJ5503][GXOI/GZOI2019]宝牌一大堆(动态规划) 题面 BZOJ 洛谷 题解 首先特殊牌型直接特判. 然后剩下的部分可以直接\(dp\),直接把所有可以存的全部带进去大力\(d ...
- [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#深度学习の接口传参(interface)-----接口的妙用
一.接口可以干嘛 我们知道,接口的本质是一个约束规范,委托是方法纵向(形式上)的封装,接口是不同方法横向(广度)的封装 接口中不能有变量,但是可以有属性方法.常见的,我们可以用接口: 1.实现需求方的 ...
- 【题解】洛谷P3660 [USACO17FEB]Why Did the Cow Cross the Road III
题目地址 又是一道奶牛题 从左到右扫描,树状数组维护[左端点出现而右端点未出现]的数字的个数.记录每个数字第一次出现的位置. 若是第二次出现,那么删除第一次的影响. #include <cstd ...
- linux目录1
1.linux常用快捷键 2.linux命令之vmstat 3.linux命令之df 4.linux命令之netstat 5.linux命令之 tar 6.The authenticity of ho ...
- Linux内核入门到放弃-无持久存储的文件系统-《深入Linux内核架构》笔记
proc文件系统 proc文件系统是一种虚拟的文件系统,其信息不能从块设备读取.只有在读取文件内容时,才动态生成相应的信息. /proc的内容 内存管理 系统进程的特征数据 文件系统 设备驱动程序 系 ...
- VirtualBox修改UUID实现虚拟硬盘的重复利用
其实,记录这个是为了留给自己看.每次用每次查,已经老到什么东西都记不住了.本次查询是从这里(VirtualBox 修改UUID实现虚拟硬盘复制)获得帮助的,感谢. 在VirtualBox把一个已经使用 ...
- win10下ElasticSearch5.5.1与head、Kibana、X-Pack、SQL、IK、PINYIN插件的配置安装
ElasticSearch5.5.1与插件的配置安装 Elasticsearch5.5.1安装: 下载地址https://www.elastic.co/cn/downloads/elasticsear ...
- codeforces#1132 F. Clear the String(神奇的区间dp)
题意:给出一个字符串S,|S|<=500.每次操作可以删除一段连续的相同字母的子串.问,最少操作多少次可以把这个字符串变成空串. 分析:刚开始的思路是,把连续的串给删除掉,然后再....贪心.完 ...
- MySQL的运算符及其优先级
+++++++++++++++++++++++++++++++++++++++++++标题:MySQL的常见运算符时间:2019年2月23日内容:MySQL的常见运算符重点:主要讲述MySQL常见运算 ...
- 第二部分之RDB持久化(第十章)
RDB持久化功能所生成的RDB文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时的数据库状态.(数据库状态:服务器中的非空数据库以及它们的键值对统称为数据库状态) 一.RDB文件的创建 ...
- spring boot 操作MySQL pom添加的配置
1 在项目中的pom.xml配置文件添加依赖 <!--MySQL依赖 --> <dependency> <groupId>mysql</groupId> ...