[GXOI/GZOI2019]宝牌一大堆
感觉比ZJOI的麻将要休闲很多啊。
这个题就是一个最优化问题,没有面子的特殊牌型可以直接用复杂度较低的贪心判掉。
有面子的话就是一个经典dp。(曾经还在ZJOI写过这个毒瘤东西
大概就是存一下对子,面子,杠子的个数,再记一下上两个位置剩余的牌的个数,转移非常简单。
写起来挺爽的。
#include<bits/stdc++.h>
#define N 55
#define eps 1e-7
#define inf 1e18+7
#define db double
#define ll long long
#define ldb long double
using namespace std;
inline ll read()
{char ch=0;ll x=0,flag=1;while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*flag;
}
map<string,ll>mp;
bool h[N],flag[N],chk[N][N][N];
ll tot,ans,a[N],b[N],cnt[N],C[N][N];
void prepare()
{//万 mp["1m"]=++tot;mp["2m"]=++tot;mp["3m"]=++tot;mp["4m"]=++tot;mp["5m"]=++tot;mp["6m"]=++tot;mp["7m"]=++tot;mp["8m"]=++tot;mp["9m"]=++tot;//筒 mp["1p"]=++tot;mp["2p"]=++tot;mp["3p"]=++tot;mp["4p"]=++tot;mp["5p"]=++tot;mp["6p"]=++tot;mp["7p"]=++tot;mp["8p"]=++tot;mp["9p"]=++tot;//索mp["1s"]=++tot;mp["2s"]=++tot;mp["3s"]=++tot;mp["4s"]=++tot;mp["5s"]=++tot;mp["6s"]=++tot;mp["7s"]=++tot;mp["8s"]=++tot;mp["9s"]=++tot; //其它mp["E"]=++tot;mp["S"]=++tot;mp["W"]=++tot;mp["N"]=++tot;mp["Z"]=++tot;mp["B"]=++tot;mp["F"]=++tot;//组合数 for(ll i=0;i<=10;i++){C[i][0]=1;for(ll j=1;j<=i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];}//预处理可以凑面子的位置for(ll i=1;i<=27;i++)h[i]=true;h[1]=h[2]=h[10]=h[11]=h[19]=h[20]=false;//预处理合法状态 chk[1][4][0]=chk[1][3][1]=chk[1][2][2]=chk[1][1][3]=true;for(ll i=1;i>=0;i--)for(ll j=4;j>=0;j--)for(ll k=4;k>=0;k--)if(chk[i][j][k]){if(i)chk[i-1][j][k]=true;if(j)chk[i][j-1][k]=true;if(k)chk[i][j][k-1]=true;}
}
void clear()
{ans=0;for(ll i=0;i<=4;i++)a[i]=b[i]=0;for(ll i=1;i<=tot;i++)cnt[i]=4,flag[i]=false;
}
ll ksm(ll x,ll k)
{ll ans=1;while(k){if(k&1)ans*=x;k>>=1;x*=x;}return ans;
}
ll work1()//七对子
{ll k,now=0,ans=7;k=min(a[4],7-now);now+=k;ans*=ksm(24,k);k=min(a[3],7-now);now+=k;ans*=ksm(12,k);k=min(b[4],7-now);now+=k;ans*=ksm(6,k);k=min(a[2],7-now);now+=k;ans*=ksm(4,k);k=min(b[3],7-now);now+=k;ans*=ksm(3,k);k=min(b[2],7-now);now+=k;ans*=ksm(1,k);k=min(a[4],7-now);now+=k;ans/=ksm(6,k);ans*=ksm(4,k);k=min(b[4],7-now);now+=k;ans/=ksm(6,k);ans*=ksm(1,k);if(now==7)return ans;else return -inf;
}
ll work2()//国士无双
{bool ok=false;ll p[20],now=13,ans=0;p[1]=1;p[2]=9;p[3]=10;p[4]=18;p[5]=19;p[6]=27;p[7]=28;p[8]=29;p[9]=30;p[10]=31;p[11]=32;p[12]=33;p[13]=34;for(ll i=1;i<=13;i++){ll x=p[i];if(!cnt[x])return -inf;if(cnt[x]>=2)ok=true;now*=cnt[x];if(flag[x])now*=2;}if(!ok)return -inf; for(ll i=1;i<=13;i++){ll x=p[i];if(cnt[x]==2)ans=max(ans,(now/2)*1*(flag[x]?2:1));if(cnt[x]==3)ans=max(ans,(now/3)*3*(flag[x]?2:1));if(cnt[x]==4)ans=max(ans,(now/4)*6*(flag[x]?2:1));}return ans;
}
ll dp[2][5][4][5][5][5],DP[2][5][4][5][5][5];
void update(ll &x,ll k){x=max(x,k);}
ll work3()//各种杠子+面子+雀头
{memset(DP,-1,sizeof(DP));DP[0][0][0][cnt[1]][0][0]=1;for(ll i=1;i<=tot;i++){ll lx=cnt[i],ly=(i<=1)?0:cnt[i-1],lz=(i<=2)?0:cnt[i-2];for(ll a=0;a<=1;a++)for(ll b=0;b<=4;b++)for(ll c=0;c<=3;c++)if(chk[a][b][c])for(ll x=0;x<=4;x++)for(ll y=0;y<=4;y++)for(ll z=0;z<=4;z++)dp[a][b][c][x][y][z]=DP[a][b][c][x][y][z],DP[a][b][c][x][y][z]=-1;for(ll a=0;a<=1;a++)for(ll b=0;b<=4;b++)for(ll c=0;c<=3;c++)if(chk[a][b][c])for(ll x=0;x<=lx;x++)for(ll y=0;y<=ly;y++)for(ll z=0;z<=lz;z++){ll o=dp[a][b][c][x][y][z];if(o<=0)continue;if(x>=2&&a!=1)update(dp[a+1][b][c][x-2][y][z],o);if(x>=3&&b!=4)update(dp[a][b+1][c][x-3][y][z],o);if(x>=4&&c!=3)update(dp[a][b][c+1][x-4][y][z],o);if(x&&y&&z&&b!=4&&h[i])update(dp[a][b+1][c][x-1][y-1][z-1],o);if(i<=2)update(DP[a][b][c][cnt[i+1]][x][y],o);else{ll k=cnt[i-2]-z;o*=C[cnt[i-2]][k]*(flag[i-2]?ksm(2,k):1);update(DP[a][b][c][cnt[i+1]][x][y],o);}}}ll ans=0;for(ll a=0;a<=1;a++)for(ll b=0;b<=4;b++)for(ll c=0;c<=3;c++)if(chk[a][b][c])for(ll x=0;x<=cnt[tot-0];x++)for(ll y=0;y<=cnt[tot-1];y++)for(ll z=0;z<=cnt[tot-2];z++){ll ka=cnt[tot-0]-x,kb=cnt[tot-1]-y,kc=cnt[tot-2]-z;dp[a][b][c][x][y][z]*=C[cnt[tot-0]][ka]*(flag[tot-0]?ksm(2,ka):1);dp[a][b][c][x][y][z]*=C[cnt[tot-1]][kb]*(flag[tot-1]?ksm(2,kb):1);dp[a][b][c][x][y][z]*=C[cnt[tot-2]][kc]*(flag[tot-2]?ksm(2,kc):1);if(a==1&&b==4&&c==0)ans=max(ans,dp[a][b][c][x][y][z]);if(a==1&&b==3&&c==1)ans=max(ans,dp[a][b][c][x][y][z]);if(a==1&&b==1&&c==3)ans=max(ans,dp[a][b][c][x][y][z]);if(a==1&&b==4&&c==0)ans=max(ans,dp[a][b][c][x][y][z]);}return ans;
}
ll work4()//特殊处理4杠子+1对子
{ll ans=-inf;for(ll i=2;i<=4;i++)if(a[i]){a[i]--;ll k,v=4*C[i][2],now=0;k=min(a[4],4-now);now+=k;v*=ksm(16,k);k=min(b[4],4-now);now+=k;v*=ksm(1,k);if(now==4)ans=max(ans,v);a[i]++;}for(ll i=2;i<=4;i++)if(b[i]){b[i]--;ll k,v=1*C[i][2],now=0;k=min(a[4],4-now);now+=k;v*=ksm(16,k);k=min(b[4],4-now);now+=k;v*=ksm(1,k);if(now==4)ans=max(ans,v);b[i]++;} return ans;
}
void solve()
{clear(); while(true){string s;cin>>s;if(s[0]=='0')break;cnt[mp[s]]--;}while(true){string s;cin>>s;if(s[0]=='0')break;flag[mp[s]]=true;}for(ll i=1;i<=tot;i++)if(flag[i])a[cnt[i]]++;else b[cnt[i]]++;ans=max(ans,work1());ans=max(ans,work2());ans=max(ans,work3());ans=max(ans,work4());printf("%lld\n",ans);
}
int main()
{prepare();ll t=read();for(ll i=1;i<=t;i++)solve();return 0;
}
转载于:https://www.cnblogs.com/Creed-qwq/p/10772166.html
[GXOI/GZOI2019]宝牌一大堆相关推荐
- [GXOI/GZOI2019]宝牌一大堆(dp)
luogu bzoj 这个麻将题还算挺友善的,比隔壁zjoi的要好得多... 比较正常的做法是五维dp 但事实上六维dp也是完全不会被卡的 七对子选权值最高的七个,国士无双直接$13^2$暴力 ...
- 题解 P5301 【[GXOI/GZOI2019]宝牌一大堆】
这道题除了非常恶心以外也没有什么非常让人恶心的地方 当然一定要说有的话还是有的,就是这题和咱 ZJOI 的 mahjong 真的是好像的说~ 于是就想说这道题出题人应该被 锕 掉 noteskey 整 ...
- LOJ#3084. 「GXOI / GZOI2019」宝牌一大堆(递推)
题面 传送门 题解 为什么又是麻将啊啊啊!而且还是我最讨厌的爆搜类\(dp\)-- 首先国士无双和七对子是可以直接搞掉的,关键是剩下的,可以看成\(1\)个雀头加\(4\)个杠子或面子 直接\(dp\ ...
- 【GXOI/GZOI2019】宝牌一大堆(麻将DP)(贪心)
传送门 其实还有第三种麻将--四川麻将,规则和其他麻将都不太像,甚至在四川不同地区的规则也不一样. 而关于麻将胡牌的题,能够利用DP解决的,我们可以将这种技巧成为麻将DP 题解: 这篇题解里面用的是川 ...
- 【LOJ #3084】【GXOI / GZOI2019】—宝牌一大堆(DP)
传送门 首先把国士无双和七对子判掉 实际上可以发现杠根本没用 因为(43)>(44)∗2{4\choose 3}>{4\choose 4}*2(34)>(44)∗2 设f[i][ ...
- GXOI/GZOI2019题解
GXOI/GZOI2019题解 P5300 [GXOI/GZOI2019]与或和 一眼题.. 显然枚举每个二进制位,答案就变成了全1子矩阵数量. 这个xjb推推,单调栈一下就行了. #include& ...
- [GXOI/GZOI2019]旧词——树链剖分+线段树
题目链接: [GXOI/GZOI2019]旧词 对于$k=1$的情况,可以参见[LNOI2014]LCA,将询问离线然后从$1$号点开始对这个点到根的路径链修改,每次询问就是对询问点到根路径链查询即可 ...
- [数据结构专训][GXOI/GZOI2019]旧词,[hdu5118]GRE Words Once More!,[hdu6333]Problem B. Harvest of Apples
文章目录 T1:[GXOI/GZOI2019]旧词 solution code T2:GRE Words Once More! solution code T3:Problem B. Harvest ...
- 【LOJ】#3086. 「GXOI / GZOI2019」逼死强迫症
LOJ#3086. 「GXOI / GZOI2019」逼死强迫症 这个就是设状态为\(S,j\)表示轮廓线为\(S\),然后用的1×1个数为j 列出矩阵转移 这样会算重两个边相邻的,只要算出斐波那契数 ...
最新文章
- unity 200.8m yoy_专场分享会|大会最新Unity、中创文旅专场预告来啦!
- python 获取当前时间 时间差
- hihocoder 1320 压缩字符串(字符串+dp)
- 数据库连接池——C3P0:数据库连接池技术
- CL_CRM_REPORT_QUESTION call CRM_REPORT_RF_CHECK_AUTHORITY
- scope python_Python标准库Scope
- pandas plot label_Python+Pandas | 分析比特币与股票市场的关系
- 教你把gps服务器修改为中国加速搜星,Android的GPS加速搜星的原理和方法
- java s类型_javasript基础——数据类型与数据类型转换
- 设计一个几何图形的面积计算器,希望这个计算器可以计算圆和矩形等图形的面积
- Android开发笔记(一百八十一)使用CameraX拍照
- C语言贪心算法——找钱
- 关于微信小程序中的取整
- 使用CSS过滤器让透明的彩色png图像变纯白
- 最新FL Studio 21中文版发布啦!全新的FL音频剪辑封套、主题和插件
- 微型计算机原理与应用课件,微机原理与应用课件
- Python爬虫抓取某音乐网站MP3(下载歌曲、存入Sqlite)
- ARP攻击与ARP欺骗
- 【转】Python之optparse模块OptionParser的使用方法
- logins登录项目