[洛谷P2540]【NOIP2015】斗地主增强版(DP+搜索)

文章目录

题目

P2540 斗地主增强版

分析

如果不出顺子,那么怎么出最优是可以DP解决的: d p [ i ] [ j ] [ k ] [ l ] dp[i][j][k][l] dp[i][j][k][l]表示一副牌有 i i i个炸弹、 j j j个三张、 k k k个顺子、 l l l个单牌的最优出法。在这个状态定义下,原来的 4 i + 3 j + 2 k + l 4i+3j+2k+l 4i+3j+2k+l张牌变成了 i + j + k + l i+j+k+l i+j+k+l张牌,你只需要考虑怎么组合(下面用 i i i j j j l l l l l l分别代指“炸弹”“三张”“对子”“单牌”这四种牌):

  • 一张一张出完;
  • 出一张 i i i,状态转移;
  • 将一张 i i i变成一张 j j j和一张 l l l,状态转移(“炸弹”拆成一个三张和一个单牌);
  • ……(共 13 13 13种情况,详见代码)

这样就可以轻(jue)松(wang)地完成DP了。

然后Dfs搜索顺子的打法,打了顺子过后就直接用上面的 d p dp dp值,将剩下的牌打完即可,注意处理一下大小王的情况(这道题里面大小王不算对子)。

代码

突然爱上了打空格XD

#
信息传递问题涉及图论中的最小环查找,具体来说是寻找一个有向图中最小的环的长度。在洛谷 P2661 [NOIP2015 提高组] 信息传递中,每个节点仅有一个出边,因此可以简化为寻找最小环的问题。 ### 问题分析 本题可以理解为在一个有向图中,每个节点的出度为1,因此图的结构是由若干个环和指向这些环的链组成。由于题目要求找出最小的环,因此可以忽略链的部分,仅关注环的长度。 ### 解决思路 1. **图的构建**:使用数组 `a` 来表示每个节点的出边,数组 `b` 来记录每个节点的入度。 2. **删除链**:通过递归函数 `cut()` 删除入度为0的节点,从而将图中所有链的部分删除,仅保留环。 3. **计算最小环**:遍历剩下的节点,找到最小的环长度。 ### 代码实现 ```cpp #include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAXN = 200010; LL n, ans = 0x7f7f7f7f; LL a[MAXN], b[MAXN]; // 删除入度为0的节点及其边 void cut(LL s) { b[a[s]]--; if (b[a[s]] == 0) cut(a[s]); a[s] = -1; } // 计算环的长度 LL Sum(LL bgn, LL idx, LL s) { if (idx == bgn && s != 0) return s; LL idx_ = a[idx]; a[idx] = 0; return Sum(bgn, idx_, s + 1); } int main() { cin >> n; for (LL u = 1; u <= n; u++) { LL v; cin >> v; a[u] = v; b[v]++; } // 删除入度为0的节点 for (LL i = 1; i <= n; i++) { if (b[i] == 0) cut(i); } // 寻找最小环 for (LL i = 1; i <= n; i++) { if (a[i] > 0) { LL sum_ = Sum(i, i, 0); if (sum_ < ans) ans = sum_; } } cout << ans; return 0; } ``` ### 算法复杂度 - **时间复杂度**:由于每个节点和边仅被处理一次,因此总的时间复杂度为 $O(n)$。 - **空间复杂度**:使用了两个数组 `a` 和 `b`,空间复杂度为 $O(n)$。 ### 总结 本题通过图论的最小环问题进行建模,利用递归删除链部分,简化问题后直接寻找最小的环。该方法简单且高效,适用于每个节点出度为1的特殊图结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值