首页 > 其他分享 >240125 杂题选谈

240125 杂题选谈

时间:2024-01-25 20:11:46浏览次数:30  
标签:花色 int 选谈 240125 27 对子 now 杂题 dp

PKUSC2022 Mahjong

http://222.180.160.110:1024/contest/4813/problem/1


https://www.bilibili.com/video/BV1JB4y1R7AP/

这里是 PKUSC 当时的讲解视频。听说可以证明本题一定有 \(\le 5\) 的解。好神奇。


就比如说我们爆搜,\(9^4\times 13^4\) 这个显然干不动对吧,所以我们考虑反过来 DP。

我们先把字符串转化成计数数组,就是每种牌有多少片。不妨将 1m ~ 9s 编号为 \(1\sim 27\),记 \(g_i\) 为编号为 \(i\) 的牌的数量。

为什么我们觉得 DP 不好打呢?因为换牌操作可以将两个毫不相干的牌的数量更改,不好记录状态。我们不妨直接将换牌拆成 丢弃一张牌借取令一张牌 两个操作。很显然这两个操作数量是一样的,因为我们的牌数量自始至终不变。

对于比较简单的对子作为终局的情况,我们只关心对数是否为 \(7\),所以设计状态:\(dp_{i,j}\) 表示前 \(i\) 张牌中凑出 \(j\) 个对子的最小代价。

那么就分 把当前牌丢一些 / 借一些拿去组对子直接丢弃当前牌 两种方案。因为丢 / 借的数量是不确定的,直接 abs 一下就好。刷表,有:

\[dp_{i+1,j}=dp_{i,j}+g_{i+1}\\ dp_{i+1,j+1}=dp_{i,j}+|g_{i+1}-2| \]

最后我们的答案就来自 \(dp_{27,7}\)。然后注意这里我们的终局是 14 张牌 你能秒我,但起手只有 13 张牌,所以其实会有一个额外的借牌操作,假设答案为 \(x\),那么其实 \(dp_{27,7}=2\times x+1\)。


有了对子的铺垫,面子手其实也还好。我们需要考虑的是对子和面子的个数。

但是有个问题,对子只用借 / 丢当前花色,但面子可能是会借 / 丢下一个 / 下下一个花色的。

所以干脆全部记录到状态里,令 \(f_{i,j,k,a,b}\) 表示当前在第 \(i\) 个花色,凑成了 \(j\) 个面子,\(k\) 个对子,需要 \(a\) 个 \(i+1\),\(b\) 个 \(i+2\)。注意因为表示丢借有负数不太容易,不如就直接设成需要的数量了。

因为这个需要数量只是前面的花色对当前花色的需要 \(a\),我们还要满足当前花色 自身 的需要 \(now\)(也就是说当前花色一共需要 \(a+now\) 张)。注意这里 \(a\) 张全部都是拿去借给前面的花色用的,自己不能用。

  • 对于 \(k=0\) 且 \(now\ge 2\),此时可以从 \(now\) 里拿两张出来凑对子,剩下的 \(now - 2\) 因为肯定 \(\le 2\),所以只能全部拿去凑顺子。所以有:

    \[f_{i+1,j+now-2,1,b+now-2, now-2}=f_{i,j,0,a,b}+|g_{i+1}-(a+now)| \]

  • 对于 \(now\ge 3\),拿三张凑一面。有:

    \[f_{i+1,j+now-2,k,b+now-3,now-3}=f_{i,j,0,a,b}+|g_{i+1}-(a+now)| \]

  • 对于 \(now\ne 0\),可以凑顺子,有:

    \[f_{i+1,j+now,k,b+now,now}=f_{i,j,0,a,b}+|g_{i+1}-(a+now)| \]

    注意不能跨花色借牌,也就是不能让 \(i=8/9/17/18/26/27\)。

答案就是 \(f_{27,4,1,0,0}\)。


然后这两个情况取一个 \(\min\) 就是答案。

namespace XSC062 {
using namespace fastIO;
using std::cin;
using std::getline;
using str = std::string;
int g[30];
int dp[30][15];
str sm, sp, ss;
int f[30][7][2][7][7];
int abs(int x) { return x >= 0 ? x : -x; }
int min(int x, int y) { return x < y ? x : y; }
void upd(int &x, int y) { x = min(x, y); return; }
int main() {
	getline(cin, sm, 'm');
	getline(cin, sp, 'p');
	getline(cin, ss, 's');
	for (auto i : sm) ++g[i - '0'];
	for (auto i : sp) ++g[i - '0' + 9];
	for (auto i : ss) ++g[i - '0' + 18];
	// 打对子
	memset(dp, 0x3f, sizeof (dp));
	dp[0][0] = 0;
	for (int i = 0; i < 27; ++i) {
		for (int j = 0; j <= 7; ++j) {
			if (dp[i][j] == 0x3f3f3f3f) continue;
			upd(dp[i + 1][j], dp[i][j] + g[i + 1]);
			upd(dp[i + 1][j + 1], dp[i][j] + abs(g[i + 1] - 2));
		}
	}
	// 打飞机
	memset(f, 0x3f, sizeof (f));
	f[0][0][0][0][0] = 0;
	for (int i = 0; i < 27; ++i)
	for (int j = 0; j <= 4; ++j)
	for (int k = 0; k <= 1; ++k)
	for (int a = 0; a <= 4; ++a)
	for (int b = 0; b <= 4; ++b) {
		if (i % 9 == 8 && b) continue;
		if (i % 9 == 0 && a + b) continue;
		for (int now = 0; now <= 4; ++now) { // 对当前的额外需求 
			if (a + now > 4) continue;
			int v = f[i][j][k][a][b] + abs(g[i + 1] - (a + now));
			if (j + now <= 4 && b + now <= 4) // 直接硬配顺子 
				upd(f[i + 1][j + now][k][b + now][now], v);
			if (now >= 2 && !k && j + now - 2 <= 4 && b + now - 2 <= 4) // 借两个去凑对子 
				upd(f[i + 1][j + now - 2][1][b + now - 2][now - 2], v);
			if (now >= 3 && j + now - 2 <= 4 && b + now - 3 <= 4) // 借两个去凑三不带 
				upd(f[i + 1][j + now - 2][k][b + now - 3][now - 3], v);
		}
	}
	// 拿来借走会算两次 
	print(min(dp[27][7], f[27][4][1][0][0]) / 2, '\n');
	return 0;
}
} // namespace XSC062

标签:花色,int,选谈,240125,27,对子,now,杂题,dp
From: https://www.cnblogs.com/XSC062/p/17988063

相关文章

  • Trie树学习笔记+杂题(进阶1 Trie)
    前言:回来上课吧,不然真的就没人了。现在也是没有脑子一、Trie树学习笔记+杂题(进阶1Trie)相关题单:戳我1.trie树简介字典树,英文名trie。顾名思义,就是一个像字典一样的树,核心原理就是用空间换时间,利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,所以它可以处......
  • Trie树学习笔记+杂题(进阶1 Trie)
    前言:回来上课吧,不然真的就没人了。现在也是没有脑子一、Trie树学习笔记+杂题(进阶1Trie)相关题单:戳我1.trie树简介字典树,英文名trie。顾名思义,就是一个像字典一样的树,核心原理就是用空间换时间,利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,所以它可以处......
  • 20240125打卡——《构建之法》读书笔记第1~4章
    第一章概论在这一章中,作者为我们介绍了一些关于软件工程的基本知识。①软件=程序+软件工程:正是因为对软件开发活动(构建管理、源代码管理、软件设计、软件测试、项目管理)相关的内容的完成,才能完成把整个程序转化成为一个可用的软件的过程。扩展的推论:软件企业=软件+商业模式......
  • 「杂题乱刷」P1558
    好久没写cnblog了,来写一下。做一下恢复训练。P1558(色板游戏)数据结构板子题?反正我一开始是不知道怎么去维护的。反正我代码分块写的跟线段树一样思路大致是把图的颜色化成二进制,然后就很好做了,注意更新时记得顺便维护答案。给大家几个样例来调代码:hack1in:100302C1......
  • 哈希学习笔记+杂题(进阶1 字符串哈希)
    哈希杂题前言:竟然下雪了,但是天是灰蒙蒙的。一、哈希学习笔记+杂题(进阶1字符串哈希)相关题单:戳我字符串哈希因为是一种玄学做法,所以具有极强的延展性。所以再碰到字符串的题时,抛开马拉车,kmp,字典树,AC自动机,SA&SAM,先想一下哈希的做法,如果时间复杂度允许,那就可以直接上哈希(虽然你......
  • 哈希学习笔记+杂题(进阶1 字符串哈希)
    哈希杂题前言:竟然下雪了,但是天是灰蒙蒙的。一、哈希学习笔记+杂题(进阶1字符串哈希)相关题单:戳我字符串哈希因为是一种玄学做法,所以具有极强的延展性。所以再碰到字符串的题时,抛开马拉车,kmp,字典树,AC自动机,SA&SAM,先想一下哈希的做法,如果时间复杂度允许,那就可以直接上哈希(虽然你......
  • 哈希学习笔记+杂题(基础2 字符串哈希)
    哈希杂题前言:骗分神器,我之前竟然没有学。一、哈希学习笔记+杂题(基础2字符串哈希)相关题单:戳我1.哈希(hash)简介哈希算法(HashAlgorithm),又称散列算法。有两种用法,第一种就是将一字符串转化成任意进制的数,目的是方便存储。第二种就是将大范围的数映射成小范围的数,目的也是方便存......
  • 寒假集训杂题选记 2
    目录写在前面CF1288EP3538[POI2012]OKR-AHorriblePoem写在最后写在前面寒假集训期间杂题选记。CF1288E知识点:数据结构,乱搞小清新数据结构。显然\(i\)最靠上的出现位置不是1就是\(i\);\(i\)最靠下的位置一定出现在\(i\)即将被扔到顶上前或者所有操作结束之后,且此......
  • 「杂题乱刷」AT_abc337_e
    题目链接题目传送门(at)题目传送门(luogu)题意简述有\(n\)瓶果汁,其中有一瓶坏的,你需要使用最少的小白鼠使得这些小白鼠能找出已经变质的果汁的编号,对于每只小白鼠,你可以给他们喝任意瓶不重复的果汁,每瓶果汁可以被平均分。解题思路妙妙构造题。思路一:拿\(n\)个小白鼠,每个小......
  • Petrozavodsk Summer 2019. Day 9. MEX Foundation Contest【杂题】
    比赛链接A.TheOnePolynomialMan给定模数\(p\)和\(0\simp-1\)的两个集合\(U,V\),求有多少个有序对\((a,b)\)满足:\(f(a,b)=\prod\limits_{z\inV}\left(\frac{(2a+3b)^2+5a^2}{(3a+b)^2}+\frac{(2a+5b)^2+3b^2}{(3a+2b)^2}-z\right)\equiv0\pmo......