dp

#(技巧型DP)洛谷P1070 道路游戏(提高+/省选-)

白昼怎懂夜的黑 提交于 2019-11-29 02:36:13
题目描述 小新正在玩一个简单的电脑游戏。 游戏中有一条环形马路,马路上有 n n个机器人工厂,两个相邻机器人工厂之间由一小段马路连接。小新以某个机器人工厂为起点,按顺时针顺序依次将这 n n个机器人工厂编号为 1-n 1 − n,因为马路是环形的,所以第 n n 个机器人工厂和第 1 1个机器人工厂是由一段马路连接在一起的。小新将连接机器人工厂的这 n 段马路也编号为 1-n 1 − n,并规定第 i i段马路连接第 i 个机器人工厂和第 i+1 i + 1 个机器人工厂( 1≤i≤n-1 1 ≤ i ≤ n − 1),第 n n段马路连接第 n n 个机器人工厂和第 1 1个机器人工厂。 游戏过程中,每个单位时间内,每段马路上都会出现一些金币,金币的数量会随着时间发生变化,即不同单位时间内同一段马路上出现的金币数量可能是不同的。小新需要机器人的帮助才能收集到马路上的金币。所需的机器人必须在机器人工厂用一些金币来购买,机器人一旦被购买,便会沿着环形马路按顺时针方向一直行走,在每个单位时间内行走一次,即从当前所在的机器人工厂到达相邻的下一个机器人工厂,并将经过的马路上的所有金币收集给小新,例如,小新在 i i( 1≤i≤n 1 ≤ i ≤ n)号机器人工厂购买了一个机器人,这个机器人会从 i i 号机器人工厂开始,顺时针在马路上行走,第一次行走会经过 i i号马路,到达 i+1 i

洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn

这一生的挚爱 提交于 2019-11-29 02:21:44
洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Description 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚。他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方。我们假定,他的农场划分成 N x N 的方格。输入数据中包括有树的方格的列表。你的任务是计算并输出,在他的农场中,不需要砍树却能够修建的最大正方形牛棚。牛棚的边必须和水平轴或者垂直轴平行。 EXAMPLE 考虑下面的方格,它表示农夫约翰的农场,‘.'表示没有树的方格,‘#'表示有树的方格 1 2 3 4 5 6 7 8 1 . . . . . . . . 2 . # . . . # . . 3 . . . . . . . . 4 . . . . . . . . 5 . . . . . . . . 6 . . # . . . . . 7 . . . . . . . . 8 . . . . . . . . 最大的牛棚是 5 x 5 的,可以建造在方格右下角的两个位置其中一个。 Input Line 1: 两个整数: N (1 <= N <= 1000),农场的大小,和 T (1 <= T <= 10,000)有树的方格的数量 Lines 2..T+1: 两个整数(1 <= 整数 <= N), 有树格子的横纵坐标 Output 只由一行组成,约翰的牛棚的最大边长。 Sample

hdu4632(区间dp)

那年仲夏 提交于 2019-11-29 01:49:38
题意: 给定字符串,求不同回文子序列的个数(不同表示小标不同即可)。 题解: 考虑区间dp做法 dp[i][j]表示从i到j的不同子序列的个数,包含一点容斥思想。 if a[i] 和a[j]不等 dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1] (表示取i到j-1和i+1到减掉i+1到j-1的部分,因为中间加了两次) else dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1] +1+dp[i+1][j-1] =dp[i][j-1]+dp[i+1][j]+1 。(这里好理解了,加上单独取i和j,取i和j之后取中间的部分就不存在重复啦) 代码: #include <iostream> #include<bits/stdc++.h> using namespace std; const int mod=1e4+7; string s; int dp[1005][1005]; //dp[i][j]表示区间i到j的最长回文串数目 int main() { int T; scanf("%d",&T); for(int kase=1;kase<=T;kase++){ memset(dp,0,sizeof(dp)); for(int i=0;i<1005;i++)dp[i][i]=1; cin>>s; int len=s

[JLOI2013]卡牌游戏 概率DP

做~自己de王妃 提交于 2019-11-29 01:39:37
[JLOI2013]卡牌游戏 概率DP 题面 \(dfs\) 复杂度爆炸,考虑DP。发现决策时,我们只用关心当前玩家是从庄家数第几个玩家与当前抽到的牌是啥。于是设计状态 \(f[i][j]\) 表示有 \(i\) 个人时, 从庄家数第 \(j\) 个人 的胜率。又因为此时终态确定 \(f[1][1]=1\) (只有一个人时那个人胜率为100%),所以倒推回去。 转移时,枚举抽到的牌,算出从庄家数第 \(t\) 个会出局,那么下一局庄家就是第 \(t+1\) 个,当前局第 \(j\) 个就是下一局的第 \(j-t(t< j)\) 或 \(i-t+j(t> j)\) 个,状态于是就从 \(i\) 转移到了 \(i-1\) if(t>j) f[i][j]+=f[i-1][i-t+j]/m; else if(t<j) f[i][j]+=f[i-1][j-t]/m; 代码: #include <cstdio> #define MAXN 1001 using namespace std; double f[MAXN][MAXN]; int a[MAXN]; int n,m; int main(){ scanf("%d %d", &n, &m); for(int i=1;i<=m;++i) scanf("%d", &a[i]); f[1][1]=1; for(int i=2;i<=n;++i)

树形dp总结

ぃ、小莉子 提交于 2019-11-28 23:46:45
1.由根分为左右子树两部分情况 二叉苹果树 2.背包类树形dp 选课 3.树的最长链 数字转换 4.树的最大独立子集 战略游戏 5.普通树的dp 皇宫看守 来源: https://www.cnblogs.com/lsyyy/p/11432957.html

四叶草的魔杖 kruskal+状压DP

冷暖自知 提交于 2019-11-28 23:07:44
四叶草魔杖 问题: 魔杖护法 \(Freda\) 融合了四件武器,于是魔杖顶端缓缓地生出了一棵四叶草,四片叶子幻发着淡淡的七色光。圣剑护法 \(rainbow\) 取出了一个圆盘,圆盘上镶嵌着N颗宝石,编号为 \(0-N-1\) 。第i颗宝石的能量是 \(Ai\) 。如果 \(Ai>0\) ,表示这颗宝石能量过高,需要把 \(Ai\) 的能量传给其它宝石;如果 \(Ai<0\) ,表示这颗宝石的能量过低,需要从其它宝石处获取 \(-Ai\) 的能量。保证 \(\sum Ai\) \(=0\) 。只有当所有宝石的能量均相同时,把四叶草魔杖插入圆盘中央,才能开启超自然之界的通道。 不过,只有 \(M\) 对宝石之间可以互相传递能量,其中第 \(i\) 对宝石之间无论传递多少能量,都要花费 \(Ti\) 的代价。探险队员们想知道,最少需要花费多少代价才能使所有宝石的能量都相同? 解 我们注意到 此题 \(Ai\) 的总和为 \(0\) 画个图可知 一条边最多进行一次传递 要想代价最小应该 要删边使得 一点权和为 \(0\) 的连通图边权值最小 答案是由一个一个权值和为 \(0\) 的连通图组成的 并且 \(n\) 很小 所以想到了 \(kruskal\) 和状态压缩 \(DP\) code: #include<bits/stdc++.h> using namespace std;

LeetCode----正则表达式匹配「动态规划」

…衆ロ難τιáo~ 提交于 2019-11-28 18:53:07
题目描述 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 ' ' 的正则表达式匹配。 ~~~ '.' 匹配任意单个字符 ' ' 匹配零个或多个前面的那一个元素 ~~~ 说明 s 可能为空,且只包含从 a-z 的小写字母。 p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。 示例 输入 : s = "aa" p = "a" 输出 : false 分析 1.首先来试试正常的字符串匹配(字符串不包含 . 和 * ) public boolean match(int i, int j, String s, String p) { if(j == p.length()) // 模式串匹配完毕,匹配串匹配完则匹配完成 return i == s.length(); return s.charAt(i) == p.charAt(j) && match(i+1, j+1, s, p); } 2.接下来模式串加入字符 「.」 public boolean match(int i, int j, String s, String p) { if(j == p.length()) return i == s.length(); return (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.') && match(i

POJ_1458 Common Subsequence 【LCS】

怎甘沉沦 提交于 2019-11-28 17:55:05
一、题目    Common Subsequence 二、分析   比较基础的求最长升序子序列。   $DP[i][j]$表示的是字符串$S1[1...i]$与$S2[1...j]$的最长公共子序列长度。   状态转移:$$if s1[i] == s2[j] DP[i][j] = DP[i-1][j-1] + 1$$ $$if s1[i] != s2[j] DP[i][j] = max(DP[i-1][j], DP[i][j-1]$$   相等时好理解,不相等的时候就是考虑两个字符串分别加上这个字符后,最长的公共子序列长度。 三、AC代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 8 using namespace std; 9 #define ll long long 10 #define Min(a,b) ((a)>(b)?(b):(a)) 11 #define Max(a,b) ((a)>(b)?(a):(b)) 12 const int MAXN = 1e3; 13 char s[MAXN+13], s2[MAXN+13]; 14 int DP[MAXN+13]

[BZOJ4712]洪水

人走茶凉 提交于 2019-11-28 17:40:42
Description 小 \(A\) 走到一个山脚下,准备给自己造一个小屋。这时候,小 \(A\) 的朋友(op,又叫管理员)打开了创造模式,然后飞到山顶放了格水。于是小 \(A\) 面前出现了一个瀑布。作为平民的小A只好老实巴交地爬山堵水。那么问题来了:我们把这个瀑布看成是一个𝑛个节点的树,每个节点有权值(爬上去的代价)。小A要选择一些节点,以其权值和作为代价将这些点删除(堵上),使得根节点与所有叶子结点不连通。问最小代价。不过到这还没结束。小A的朋友觉得这样子太便宜小A了,于是他还会不断地修改地形,使得某个节点的权值发生变化。不过到这还没结束。小A觉得朋友做得太绝了,于是放弃了分离所有叶子节点的方案。取而代之的是,每次他只要在某个子树中(和子树之外的点完全无关)。于是他找到你。 \(n\le 2\times 10^5, m\le 2\times 10^5\) Solution 第一眼动态dp,还真是的,就当锻炼码力。 首先有转移 \[ dp[u] = min\{\sum_{v\in son(u)}dp[v],\ a[u]\} \] 记 \(son[u]\) 为u的重儿子(和上面的son(u)不是同一个东西), \(g[u]\) 为 u 虚儿子的 \(dp\) 值之和。 \[ dp[u] = \min\{a[u], f[son[u]] + g[u]\} \]

hdu 4576

☆樱花仙子☆ 提交于 2019-11-28 16:36:20
简单的概率dp,我们这里的关键是使用滚动数组,可以使得所谓的“无后效性”更加具体实现 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; double dp[2][504]; int n,m,l,r; int main() { while(scanf("%d%d%d%d",&n,&m,&l,&r)&&n+m+l+r!=0) { memset(dp,0,sizeof(dp)); double ans=0;//cur 利用了滚动数组,为的是其实每一次输入w改变后,无后效性并不体现完全。(也就是说,其实是有一定的后效性,所以才会滚动数组) dp[0][1]=1; int cur;cur=0; for(int j=1;j<=m;j++) { int w; scanf("%d",&w); cur^=1; w%=n; for(int i=1;i<=n;i++) { dp[cur][i]=dp[cur^1][i+w>n?i+w-n:i+w]/2+dp[cur^1][i-w<1?i-w+n:i-w]/2; } } for(int i=l;i<=r;i++) { ans+=dp[cur][i]; } printf("%.4f\n",ans); } } 来源