LOJ#3084. 「GXOI / GZOI2019」宝牌一大堆(递推)
题面
题解
为什么又是麻将啊啊啊!而且还是我最讨厌的爆搜类\(dp\)……
首先国士无双和七对子是可以直接搞掉的,关键是剩下的,可以看成\(1\)个雀头加\(4\)个杠子或面子
直接\(dp\),设\(f[i][j][k][l][x][y]\)表示考虑前\(i\)种牌,以第\(i-2\)种牌为开头的顺子张数为\(j\),以\(i-1\)为开头的顺子张数为\(k\),以\(i\)开头的顺子张数为\(l\),杠子加面子总数为\(x\),雀头个数为\(y\),的最大权值
注意一些边界条件,比方说以某一种牌开头的顺子选的不需要超过\(2\)个,因为如果选了\(3\)个完全可以拆成刻子。还有有的时候以某种牌为开头的顺子可能不合法。以及牌数加起来不能超
这里其实可以把\(l\)这一维用滚动数组滚掉
代码基本都是抄\(fcw\)的
//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
const int N=55;
inline ll max(R ll x,R ll y){return x>y?x:y;}
ll bin[N],C[N][N];int a[N],b[N];
inline ll ch(R int x,R int v){return C[a[x]][v]*bin[b[x]*v];}
int id(char *w){
if(strlen(w+1)==2){
switch(w[2]){
case 'm':return w[1]-'0';
case 'p':return 9+w[1]-'0';
case 's':return 18+w[1]-'0';
}
}else{
switch(w[1]){
case 'E':return 28;
case 'W':return 29;
case 'N':return 30;
case 'S':return 31;
case 'Z':return 32;
case 'B':return 33;
case 'F':return 34;
}
}
return -1;
}
ll c[N];
ll solve1(){
ll res=1;
fp(i,1,34)c[i]=ch(i,2);
sort(c+1,c+1+34);
fp(i,28,34)res*=c[i];return res*7;
}
int d[20]={0,1,9,10,18,19,27,28,29,30,31,32,33,34};
ll solve2(){
ll res=0,tmp;
fp(i,1,13){
tmp=ch(d[i],2);
fp(j,1,13)if(i!=j)tmp*=ch(d[j],1);
cmax(res,tmp);
}return res*13;
}
ll f[35][3][3][5][2];
ll solve3(){
memset(f,0,sizeof(f)),f[0][0][0][0][0]=1;
fp(i,0,34){
fp(j,0,2)if(!j||(i<=27&&i%9!=0&&i%9!=1)){
fp(k,0,2)if(!k||(i<=27&&i%9!=8&&i%9!=0))
if(a[i+1]>=j+k){
fp(x,j+k,4)fp(y,0,1)if(f[i][j][k][x][y]){
for(R int z=0;z<=2&&j+k+z<=a[i+1]&&x+z<=4;++z)
for(R int w=0;j+k+z+w*3<=a[i+1]&&x+z+w<=4;++w){
int t=j+k+z+w*3;
cmax(f[i+1][k][z][x+z+w][y],f[i][j][k][x][y]*ch(i+1,t));
if(!y&&t+2<=a[i+1])cmax(f[i+1][k][z][x+z+w][1],f[i][j][k][x][y]*ch(i+1,t+2));
}
if(a[i+1]-j-k==4&&x<4)cmax(f[i+1][k][0][x+1][y],f[i][j][k][x][y]*ch(i+1,4));
}
}
}
}
return f[34][0][0][4][1];
}
void init(){
bin[0]=1;fp(i,1,18)bin[i]=bin[i-1]<<1;
fp(i,0,4){
C[i][0]=1;
fp(j,1,i)C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
char w[15];
void solve(){
fp(i,1,34)a[i]=4,b[i]=0;
while(true){
scanf("%s",w+1);
if(w[1]=='0')break;
--a[id(w)];
}
while(true){
scanf("%s",w+1);
if(w[1]=='0')break;
b[id(w)]=1;
}
printf("%lld\n",max(solve1(),max(solve2(),solve3())));
}
int main(){
// freopen("testdata.in","r",stdin);
int T;scanf("%d",&T);init();
while(T--)solve();
return 0;
}
LOJ#3084. 「GXOI / GZOI2019」宝牌一大堆(递推)的更多相关文章
- 「GXOI / GZOI2019」宝牌一大堆 (DP)
题意 LOJ传送门 题解 可以发现「七对子」 和 「国士无双」直接暴力就行了. 唯一的就是剩下的"3*4+2". 考试的时候写了个爆搜剪枝,开了O2有50pts.写的时候发现可以D ...
- Loj #3085. 「GXOI / GZOI2019」特技飞行
Loj #3085. 「GXOI / GZOI2019」特技飞行 题目描述 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代 ...
- LOJ#3083.「GXOI / GZOI2019」与或和_单调栈_拆位
#3083. 「GXOI / GZOI2019」与或和 题目大意 给定一个\(N\times N\)的矩阵,求所有子矩阵的\(AND(\&)\)之和.\(OR(|)\)之和. 数据范围 \(1 ...
- LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)
题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...
- LOJ#3087. 「GXOI / GZOI2019」旅行者(最短路)
题面 传送门 题解 以所有的感兴趣的城市为起点,我们正着和反着各跑一边多源最短路.记\(c_{0/1,i}\)分别表示正图/反图中离\(i\)最近的起点,那么对于每条边\((u,v,w)\),如果\( ...
- LOJ#3086. 「GXOI / GZOI2019」逼死强迫症(矩阵快速幂)
题面 传送门 题解 先考虑全都放\(1\times 2\)的方块的方案,设防\(i\)列的方案数为\(g_i\),容易推出\(g_i=g_{i-1}+g_{i-2}\),边界条件为\(g_0=g_1= ...
- LOJ#3085. 「GXOI / GZOI2019」特技飞行(KDtree+坐标系变换)
题面 传送门 前置芝士 请确定您会曼哈顿距离和切比雪夫距离之间的转换,以及\(KDtree\)对切比雪夫距离的操作 题解 我们发现\(AB\)和\(C\)没有任何关系,所以关于\(C\)可以直接暴力数 ...
- LOJ#3083. 「GXOI / GZOI2019」与或和(单调栈)
题面 传送门 题解 按位考虑贡献,如果\(mp[i][j]\)这一位为\(1\)就设为\(1\)否则设为\(0\),对\(or\)的贡献就是全为\(1\)的子矩阵个数,对\(and\)的贡献就是总矩阵 ...
- 「GXOI / GZOI2019」简要题解
「GXOI / GZOI2019」简要题解 LOJ#3083. 「GXOI / GZOI2019」与或和 https://loj.ac/problem/3083 题意:求一个矩阵的所有子矩阵的与和 和 ...
随机推荐
- 使用通配符配置action
建立struts2wildcard项目,此实例基本仿照前面前面第7点的实例改写而成.为了使用通配符,只需要改写配置文件即可.此实例未使用通配时的配置文件如下: <action name=&quo ...
- hibernate查询出的实体,set值后,自动更新到数据库
1.问题症状描述 最近在处理一个新需求问题,代码的大致逻辑是获取一个实体对象,调用该对象的set方法设置其中的某些字段,然后把修改后的实体作为参数供其他地方调用,根据返回值来决定是否更新这个 ...
- Excel数据转化为sql脚本
在实际项目开发中,有时会遇到客户让我们把大量Excel数据导入数据库的情况.这时我们就可以通过将Excel数据转化为sql脚本来批量导入数据库. 1 在数据前插入一列单元格,用来拼写sql语句. 具体 ...
- SpringAop及拦截器
一.Aop Aop,面向切面编程,提供了一种机制,在执行业务前后执行另外的代码. 切面编程包括切面(Aspect),连接点(Joinpoint).通知(Advice).切入点(Pointcut).引入 ...
- linux 一个网卡配置多个IP
在Redhat系列(redhat,Fedora,Centos,Gentoo)中的实现方法如下: 1.单网卡绑定多IP在Redhat系列中的实现方法 假设需要绑定多IP的网卡是eth0,请在/etc/s ...
- Python 使用Pandas读取Excel的学习笔记
这里介绍Python中使用Pandas读取Excel的方法 一.软件环境: OS:Win7 64位 Python 3.7 二.文件准备 1.项目结构: 2.在当前实验文件夹下建立一个Source文件夹 ...
- TLB与内存寻址,内存读取,虚拟内存的相关原理
TLB(Translation Lookaside Buffer)转换检测缓冲区是一个内存管理单元,用于改进虚拟地址到物理地址转换速度的缓存. TLB是一个小的,虚拟寻址的缓存,其中每一行都保存着一个 ...
- Oracle GoldenGate 四、数据过滤和数据项匹配
写在开始前 从两周前我花了大量的业余时间阅读GoldenGate官方文档,并根据文档实践和进一步学习了解GoldenGate,以下便是根据官方文档理解总结的GoldenGate学习内容: Oracle ...
- swoole集群 nginx配置
nginx配置文件: upstream cat { server 192.168.149.133:9502 weight=5; server 192.168.149.134:9502 weight=5 ...
- ubuntu解压文件命令大全
ubuntu 下rar解压工具安装方法: 压缩功能 安装 sudo apt-get install rar 卸载 sudo apt-get remove rar 解压功能 安装 sudo apt-ge ...