dp

P1941 飞扬的小鸟[dp]

一笑奈何 提交于 2019-12-02 05:10:39
题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为 n n ,高为 m m 的二维平面,其中有 k k 个管道(忽略管道的宽度)。 小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。 小鸟每个单位时间沿横坐标方向右移的距离为 11,竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度 X X ,每个单位时间可以点击多次,效果叠加;如果不点击屏幕,小鸟就会下降一定高度 Y Y 。小鸟位于横坐标方向不同位置时,上升的高度 X X 和下降的高度 Y Y 可能互不相同。 小鸟高度等于 00 或者小鸟碰到管道时,游戏失败。小鸟高度为 m m 时,无法再上升。 现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟最多可以通过多少个管道缝隙。 解析 这题比较复杂,我们慢慢分析。 首先容易看出这是道dp,不难看出用 \(dp[i][j]\) 表示小鸟飞到 \((i,j)\) 的最小点击次数。 根据题意,容易得出转移方程: \[ dp[i][j]=min(dp[i-1][j-k*up[i-1]]

最长公共子序列

蹲街弑〆低调 提交于 2019-12-02 03:39:10
定义dp[i][j]为a中前i个与b中前j个能匹配的最大长度 当 a[i] == b[j] 时,答案来自 dp[i - 1][j - 1] + 1 否则,来自dp[i - 1][j]与dp[i][j-1]中较大一个 for(rint i = 1;i <= n; ++i) { for(rint j = 1;j <= m; ++j) { if(a[i] == b[j]) dp[i][j] = dp[i - 1][j - 1] + 1; else dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]); } } 来源: https://www.cnblogs.com/Thomastine/p/11729351.html

习题:小奇探险(单调队列 & dp)

前提是你 提交于 2019-12-02 03:33:01
题目 小奇去遗迹探险,遗迹里有 $N$ 个宝箱,有的装满了珠宝,有的装着废品。 小奇有地图,所以它知道每一个宝箱的价值,但是它不喜欢走回头路,所以要按顺序拿这 $N$ 个宝箱中的若干个。 拿宝箱很累的。一开始小奇的体力是 $1$,每得到一个宝箱之后,小奇得到的价值是体力 $\times$ 宝箱的价值,之后它的体力就会变为原来的 $k$ 倍 $(0<k<1)$。 小奇不喜欢连续放过很多宝箱,所以任意一段长度为 $M$ 的序列中,小奇一定要取走其中的一个宝箱。 现在小奇想知道它能得到的最大价值和。 第一行,两个整数 $N,M$,表示的含义如题目中所述; 第二行,一个小数 $k$,表示的含义如题目中所述,最多 $4$ 位小数; 第三行,$N$ 个整数,第 $i$ 个整数表示第 $i$ 个宝箱的价值。 输出一行,一个实数,表示小奇能得到的最大价值和,四舍五入保留两位小数。 思路 额。。。 考试之中的唯一一道水题 考虑从dp[i]转移到dp[i+k] 发现,转移需要考虑的要素太多,写起来太麻烦 但是如果从dp[i+k]转移到dp[i] 是不是简单了许多 $dp_i$表示前i号节点的最大值 $dp _i =max(dp_j*k+c_i,c_i) (i<j)$ 看到这个转移方程, 发现k为定值,c~i~也为定值 之后又单调队列进行优化就行了 代码 #include<iostream>

【CF55D】Beautiful numbers

跟風遠走 提交于 2019-12-02 02:51:41
【CF55D】Beautiful numbers 题面 洛谷 题解 考虑到如果一个数整除所有数那么可以整除他们的 \(lcm\) ,而如果数 \(x\) 满足 \(x\bmod Lcm(1,2...,9)=r\) ,且 \(r\bmod Lcm\{x有的数\}=0\) ,那么这个数一定满足条件。 因为 \(Lcm(1,2...,9)=2520\) 比较小,所以我们可以存下来。 考虑数位dp,我们设 \(f[i][lcm][r]\) 表示目前 \(dp\) 到第 \(i\) 位,当前已选的数的 \(lcm\) 为 \(lcm\) ,前面几位 \(\bmod 2520\) 为 \(r\) 的数的个数。 因为 \(lcm\) 实际上最多 \(48\) 个,那么我们将这 \(48\) 个数离散一下, \(dp\) 数组的空间就开得下了,再按照普通数位 \(dp\) 的思路转移一下就可以了。 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int Mod = 2520; long long L, R; int num[20], cnt, mp[2521],

LeetCode132.分割回文串2

心不动则不痛 提交于 2019-12-02 02:29:25
leetcode132.分割回文串2 (动态规划) 状态:dp[i]表示字符串s[0...i]最少的分割次数。 状态转移:dp[i] = min(dp[i], dp[j-1] + 1, 0=<j<=i&&s[j...i]是回文串)。 边界:dp[0] = 0。 在实现的过程中可以使用快速回文法( https://blog.csdn.net/qq_22080999/article/details/80931999 )。定义二维数组p[j][i]表示s[j...i]是回文串。通过此方法可以提高计算速度。 class Solution { public: //132.分割回文串2 bool isPali(string s, int j, int i) { while (j < i) { if (s[j] != s[i]) return false; i--; j++; } return true; } int minCut(string s) { if (s.size() < 2) return 0; vector<int> dp(s.size(), s.size()); vector<vector<bool>> p(s.size(), vector<bool>(s.size(), false)); dp[0] = 0; p[0][0] = true; for (int i = 1; i

luoguP1357 花园

心已入冬 提交于 2019-12-02 00:34:55
首先对于 \(n<10^5\) 的范围,我们可以直接状压 \(dp\) . 设 \(dp[i][s]\) 表示 \(dp\) 到了第 \(i\) 位,最后 \(m\) 个状态的二进制压缩为 \(s\) 的方案数. \(\therefore dp[i][s]=dp[i-1][\frac{s}{2}]+dp[i-1][(\frac{s}{2}+2^{m-1}]\) . 但是这个题显然线性做法会超时. 于是使用套路:矩阵快速幂! 认真观察这个 \(dp\) 方程,我们可以发现对于任意一个合法状态的转移总是单一的,并且总是那个合法的 \(bool\) 矩阵. 于是我们可以对于中间状态 \(T\) 自乘 \(n\) 次,在对于每一个合法的初始状态,算出它的贡献,求和即可. #pragma GCC optimize(3) #include<bits/stdc++.h> #define il inline #define rg register using namespace std; typedef long long ll; const int mod = 1e9 + 7, O = 55; ll n; int m, k, res, ans, sta[O]; struct Matrix { int a[O][O]; Matrix() { memset(a, 0, sizeof a); } il

DP3 1012

≡放荡痞女 提交于 2019-12-01 18:45:23
游戏 有n个数,编号从1到n。现在把n个数分成k组编号为1到k,使得每组内的数必须连续,组与组之间不能相交并且每个数必须属于一个组。 游戏进行的过程如下: 1. 如果n个数都已经获得了,游戏结束。否则,找到编号最小没有全部获得的组X。 2. 游戏系统会给一个空的盒子,对于组X中已经获得的数i,将ti张写着数i的卡片放入盒子中,对于组X中最小的没有获得的数j,将tj张写着数j的卡片放入盒子中。 3. 随机从盒子中抽取一张卡片,表示当前获得的数字,然后等待1小时的冷却时间后跳转到过程1。 现在需要确定一个最好的分组,使得这个游戏期望结束的时间最小。 对于100%的数据,1 <= n <= 200000, 1 <= k <= min(50, n),1 <= ti <= 100000。 题解 对于每一组的时间很好推,就是 $\sum_{i=1}^{j} \frac{sum_{i}}{t_{i}}$ f[i][j]表示前i个数字分成j组的最小时间,很容易得到dp方程 $dp[i][j]=min(dp[k][j-1]+\sum_{p=k+1}^{i} \frac{sum_{p}-sum_{k}}{t_{p}})$ 化简 $f[k][j-1]+\sum_{p=k+1}^{i} \frac{sum_{p}}{t_{p}}-\sum_{p=k+1}^{i} \frac{sum_{k}}{t_{p}}

HDU 1502 Regular Words

不问归期 提交于 2019-12-01 18:44:05
这题是动态规划,需要:打表,字符数组,动态规划。 状态表示:dp[i][j][k]表示的是有i个A,j个B和k个C满足要求的有多少种 转移方程:dp[i][j][k]=dp[i-1][j][k]+dp[i][j-1][k]+dp[i][j][k-1] 边界:dp[0][0][0]=1; 因为会暴int,暴long long所以转换成字符数组来操作 #include<bits/stdc++.h> using namespace std; int n; char dp[65][65][65][110]; void add(int i,int j,int k) { for(int l=1;l<=100;l++) { if(i-1 >= j && j >= k &&i-1>=0&&dp[i-1][j][k][l]!=0) dp[i][j][k][l] += dp[i-1][j][k][l]; if(i >= j-1 && j-1 >= k &&j-1>=0&&dp[i][j-1][k][l]!=0) dp[i][j][k][l] += dp[i][j-1][k][l]; if(i >= j && j >= k-1 &&k-1>=0&&dp[i][j][k-1][l]!=0) dp[i][j][k][l] += dp[i][j][k-1][l]; } for(int l=1;l<=100;l

树形依赖的背包 树形dp

元气小坏坏 提交于 2019-12-01 13:43:07
树形DP有一个独特的优化,就是通过递归,枚举目前有效的元素个数,求dp[ i ][ j ] (表示 选取以i为根的子树中有选取j个元素的最大取值) (搭配 siz 数组表示当前该节点的总共子孙数) 1. hdu1561 (树形依赖背包裸题) 注意 siz 数组的运用,以及 u 点选择的节点数时要逆向枚举,就像01背包 复杂度看似O(n^3),实际是 O( n^2 ) 左右。 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 250; vector<int> g[maxn]; int dp[maxn][maxn]; int val[maxn]; int siz[maxn]; int n,m; //dp[i][j] 表示 选取以i为根的子树中有选取j个元素的最大取值 void dfs(int u){ siz[u]=1; dp[u][1] = val[u]; for(int i=0; i<g[u].size(); i++){ int v = g[u][i]; dfs(v); //这里的siz[u]不包括siz[v] ,并且是把效率很低的2^n举法用01背包来做 for

[ZJOI2008]骑士

我们两清 提交于 2019-12-01 13:20:33
Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各 界的赞扬。最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境 中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一 个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一 些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出 征的。战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有 的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的 情况),并且,使得这支骑士军团最具有战斗力。为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战 斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。 Input 第一行包含一个正整数N,描述骑士团的人数。接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力 和他最痛恨的骑士。N ≤ 1 000 000,每名骑士的战斗力都是不大于 1 000 000的正整数 Output 应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。 Sample Input 3 10 2