动态规划
图一乐图一乐
这个作者很懒,什么都没留下…
展开
-
D. Two Pirates -2(经典概率dp倒着来)
描述:有n个宝贝,玩家1每次会拿剩下的宝贝中最贵的,玩家2则是随机选。思路:正着想不太好做。然后经典倒着来,其实这个也是有原因的,我们发现问题的关键在于玩家1想去拿上上一层最贵的宝贝时,宝贝可能被上一层的玩家2拿走了,这个其实就是要枚举玩家2上一层选的宝贝是比当前贵还是便宜也就是枚举左右侧。做法:倒着来,问题转化为向一个空的盒子放球,黑球是玩家1放的,白球是玩家2放的。dp[i][j]表示放完i个球后,从左往右数第j个球是黑色的。放黑球时,保证当前放入的求是最大的,那么插入最右边,其他的继承。放白球时,原创 2021-03-02 19:40:37 · 564 阅读 · 0 评论 -
P4284 [SHOI2014]概率充电器(概率期望,换根dp,条件概率)
题意:给出一颗n个点,n-1条边的树,每个结点都有其初始化的被点亮的概率,每条边也有其可以通电的概率,求能被点亮的灯的数量的期望。分析与总结:通过这道树形dp,加深了对换根的理解,对于解决一些有依赖性关系的问题,我们可以考虑高斯消元/换根dp,主要套路为先一遍dfs求出每个结点只考虑子节点中贡献,那么作为根,它的答案就是和我们想求的一致的。然后考虑换根,建议画图理解,主要思想是将父节点中的贡献排除这个点的贡献(在这里是个条件概率公式),然后这个点依赖是它的子树和父节点连接的那一坨的贡献。Latex太烦了原创 2020-12-08 12:10:35 · 249 阅读 · 1 评论 -
牛客网,和与或(状态压缩)
题意:给你一个数组R,包含N个元素,求有多少满足条件的序列A使得0 ≤ A[i] ≤ R[i]A[0]+A[1]+…+A[N-1]=A[0] or A[1]… or A[N-1]思路:等式成立的前提是如果某一二进制位上存在1,那必定是由N个元素中某一个提供,除这个数外的其他数,这一位上只能是0。#include<bits/stdc++.h>#define f(i,a,b) for( int i=a;i<=b;++i)#define ff(i,a,b) for( int i=a原创 2020-11-17 11:29:15 · 238 阅读 · 1 评论 -
D - Discrete Centrifugal Jumps(单调栈dp)
const int N = 6e5 + 5, M = 22;int a[N], f[N];int main(){ //freopen("in.txt", "r", stdin); int n; while (cin >> n) { f(i, 1, n)a[i] = in(); deque<int> pos, neg; pos.push_back(1); neg.push_back(1); f(i, 2, n) { f[i] = inf;原创 2020-09-09 12:19:49 · 182 阅读 · 0 评论 -
AcWing 1052. 设计密码(状态机+kmp)
const int N = 55, M = 105;char s[N];int nxt[N], f[N][N];void kmp_pre(char s[], int n){ int j = 0; nxt[0] = -1, nxt[1] = 0; for (int i = 2; i <= n; i++) { while (j && s[i] != s[j + 1]) j = nxt[j]; if (s[j + 1] == s[i]) j++; nx原创 2020-09-02 16:08:52 · 210 阅读 · 0 评论 -
H - Queries for Number of Palindromes(dp,记忆化搜索,hash)
思路:设f[l][r]f[l][r]f[l][r]表示求解的范围,可以想到递归方程:f[l][r]=f[l+1][r]+f[l][r−1]−f[l+1][r−1]+vis[l][r]f[l][r]=f[l+1][r]+f[l][r-1]-f[l+1][r-1]+vis[l][r]f[l][r]=f[l+1][r]+f[l][r−1]−f[l+1][r−1]+vis[l][r],其中vis[l][r]vis[l][r]vis[l][r]表示这段是否是回文,这里可以暴力N*N求,当然如果N更大,考虑hash预处原创 2020-09-01 22:43:18 · 158 阅读 · 0 评论 -
AcWing 218. 扑克牌(记忆化dp,概率分析)
const int N = 14, M = 5;double f[N][N][N][N][M][M];int limit[7];double dp(int a, int b, int c, int d, int x, int y){ double &v = f[a][b][c][d][x][y]; if (v >= 0)return v; int na = a + (x == 0) + (y == 0); int nb = b + (x == 1) + (y == 1);原创 2020-08-25 20:47:37 · 375 阅读 · 0 评论 -
D. Makoto and a Blackboard(dp,积性函数)
思路:考虑n的所有质因子,求其期望,再乘起来。考虑dp数组,第一维表示当前是第几步,第二维表示当前因子的次数,然后每次对每种次数进行更新,次数高的可以向低的等概率转移。const int N = 1e4+5;ll n, k;ll INV[65];ll f[N][65];ll cal(ll num, int cishu){ f(i, 0, cishu - 1)f[0][i] = 0; f[0][cishu] = 1; f(i,1,k) f(j, 0, cishu) { f[i][原创 2020-08-20 19:31:56 · 153 阅读 · 0 评论 -
AcWing 1069. 凸多边形的划分(区间dp+高精度)
const int N = 55;ll w[N], f[N][N][N],n;void add(ll a[], ll b[]){ static ll c[N]; memset(c, 0, sizeof c); for (int i = 0, t = 0;i < N;i++) { t += b[i] + a[i]; c[i] = t % 10; t = t / 10; } memcpy(a, c, sizeof c);}void pri(ll a[]){ int i原创 2020-07-08 21:41:02 · 180 阅读 · 0 评论 -
环形石子合并(区间dp模板题)
int f[410][410], g[410][410], p[410];int main(){ //freopen("in.txt", "r", stdin); int n; while (cin >> n) { f(i, 1, n)scanf("%d", &p[i]), p[n + i] = p[i]; f(i, 1, 2 * n)p[i] += p[i - 1]; f(len, 2, n)//区间长度 { for (int l = 1;l + le原创 2020-07-05 12:35:01 · 113 阅读 · 0 评论 -
D. Maximum Sum on Even Positions(思维,最大连续子段和)
思路:分类讨论:1.对于交换长度为奇数的子串,偶数位上的和是不会变的。2.对于交换长度为偶数的子串,奇偶位上的和会互换。对于第二种情况,继续思考,会发现这是一个最大连续字段和的问题,对于前序贡献为负的情况,抛弃前序。然后所给的数组长度可能为奇数,所以ll a[N];int main(){ cin >> t; while (t--) { int n; scanf("%d", &n); ll now = 0; f(i, 1, n) { scanf原创 2020-06-26 12:32:52 · 307 阅读 · 0 评论 -
C. Multiplicity(dp)
优化过程:f[i][j]f[i][j]f[i][j]表示从前i个中选子串长度为j的方案数,对当前集合进行划分得到状态表示:f[i][j]=f[i−1][j−1]+f[i−1][j]f[i][j]=f[i-1][j-1]+f[i-1][j]f[i][j]=f[i−1][j−1]+f[i−1][j],发现用到的都是上一层的状态,所以改成滚动数组版本,内层从大到小,保证用的状态是上一层的,同时发现时间复杂度很高,考虑预处理出每一层可用来迭代的约数。int f[N];vector<vector<in原创 2020-06-09 15:28:52 · 173 阅读 · 0 评论