dp

1240C

天大地大妈咪最大 提交于 2020-02-04 11:28:14
贪心想了两个小时 想到怀疑人生 其实是一个简单的$dp$ $dp[i][0]$表示不选父边 $dp[i][1]$表示选 那么儿子排个序贪心一下就行了 感觉头铁总是会凉 一个想法不行要尝试换一下 #include <bits/stdc++.h> using namespace std; using ll = long long; const int maxn = 5e5 + 5; int n, k; ll dp[maxn][2]; vector<pair<int, int> > G[maxn]; void dfs(int u, int f) { vector<ll> vec; for(auto [v, w] : G[u]) { if(v != f) { dfs(v, u); dp[v][1] += w; dp[u][1] += dp[v][0]; if(dp[v][1] > dp[v][0]) { vec.push_back(dp[v][1] - dp[v][0]); } } } sort(vec.begin(), vec.end(), greater<ll>()); for(int i = 0; i < min(k - 1, (int)vec.size()); ++i) { dp[u][1] += vec[i]; } dp[u][0] = dp[u][1]; if(vec.size

完全背包问题

廉价感情. 提交于 2020-02-04 10:31:05
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 7 const int max_n = 100+2; 8 const int max_W = 10000+2; 9 10 int n,W; 11 int dp[max_n][max_W]; 12 // 定义如下: 13 // dp[i][j]:从前i个物品中,选出重量不超过j的物品 14 // dp[0][j]=0 15 // d[i][j]=? 16 // if(j<w[i]) dp[i][j]=dp[i-1][j] 17 // else dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]] + v[i]) 18 int w[max_n],v[max_n]; 19 20 void solve() 21 { 22 memset(dp,-1,sizeof(dp)); 23 // dp[0][j] = 0 24 // 初始条件 25 for(int i=0;i<=n;++i) 26 { 27 dp[0][i]=0; 28 } 29 30 for(int i=1;i<=n;++i) 31 { 32 for(int j=0;j<=W;++j) 33 { 34 if(j<w[i]) 35 {

uvalive6913 I Want That Cake(博弈dp)

泪湿孤枕 提交于 2020-02-04 02:07:34
引自:http://www.cnblogs.com/qscqesze/p/5734143.html 题意: 有两支队,每只队都有n个人,一共有m个蛋糕,每个人至少吃一个,最多吃k个。 都采取最优策略,谁吃到最后一个蛋糕,那么那只队就胜利。 按照给定的顺序去吃蛋糕,问你最后谁胜利。 思路: 先缩点,把相同的点都缩成一个点。 那么就变成了ABABABA这样交替的形式了,然后跑DP就好了。 dp[i][j]代表第i层代表的队伍蛋糕还剩j个时的状态 0为必败态,1为必胜态 首先,能把蛋糕吃完的状态为必胜态 然后,能到达必败态的状态为必胜态 只能到达必胜态的状态为必败态 递归回0,m的状态,如果为必胜态则输出第一个吃蛋糕的队伍 否则输出第二个吃蛋糕的队伍 /* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <stack> #include

UVALive 6913 I Want That Cake 博弈+dp

梦想与她 提交于 2020-02-04 02:02:42
题目链接: http://acm.hust.edu.cn/vjudge/problem/96343 I Want That Cake Time Limit: 3000MS 64bit IO Format: %lld & %llu 题意 有m块饼,有两个队各n个人站成一排,现在从第一个人开始吃饼,每个人至少吃一个最多吃k个,最后吃到饼的人所在的队伍胜,现在双方都采取最优策略,问哪个队能胜。 题解 如果两个队站队的形式是ABABAB,那么这就是个明显的博弈论了,然后并不一定是这样站的,不过没关系,我们可以把相邻的相同队伍的看成一个人,那么久变成ABABA的形式了,虽然这样处理之后每个‘人’能吃的饼的限制不同了,但是我们可以直接干一发dfs(记忆化),根据必胜态推出所有的状态。 注:必胜态:存在一个后继为必败态;必败态:所有的后继都为必胜态 代码 #include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include

Codeforces Round #605 (Div. 3)

时间秒杀一切 提交于 2020-02-03 15:01:55
https://codeforces.com/contest/1272/ A - Three Friends 题意:给三个点,每个点至多移动一格,求三个点两两之间的距离之和的最小值。 题解:排序之后中间那个点动不动无所谓,左右的点向中间靠近可以减少线段的程度至多2,长度最短减少到0。显然答案就是线段长度的两倍。 void test_case() { int a[4]; scanf("%d%d%d", &a[1], &a[2], &a[3]); sort(a + 1, a + 1 + 3); int maxd = a[3] - a[1]; if(maxd <= 2) maxd = 0; else { maxd -= 2; maxd *= 2; } printf("%d\n", maxd); } B - Snow Walking Robot 题意:给一个图,从原点开始上下左右走,走的轨迹除了原点之外不能有任何一个交点,且原点只能经过两次。给一个序列,你可以重排其中的走法,假如不行则先删除尽可能少的再重排。 题解:假如有上下左右至少各一个,那么走一个矩形。否则若只有上下或者只有左右那么就走一步就回来。 注意字符串的开始是从1开始,还调半天,真是演。 char s[100005]; void test_case() { scanf("%s", s + 1); int cntu = 0,

leetcode1048

三世轮回 提交于 2020-02-03 07:25:59
1 class Solution: 2 def __init__(self): 3 self.dp = {} 4 5 def backtrack(self,word,subword): 6 self.dp[word] = max(self.dp[word],self.dp[subword]+1) 7 for j in range(len(subword)): 8 subword2 = subword[:j] + subword[j+1:] 9 if subword2 in self.dp.keys() and self.dp[subword2] == 0: 10 self.backtrack(subword,subword2) 11 12 def longestStrChain(self, words: 'List[str]') -> int: 13 n = len(words) 14 words = sorted(words,key=lambda x:len(x)) 15 for i in range(n): 16 word = words[i] 17 self.dp[word] = 0 18 19 for word in self.dp.keys(): 20 for j in range(len(word)): 21 subword = word[:j] + word[j+1:

LeetCode 5331. 跳跃游戏 V(DP)

允我心安 提交于 2020-02-03 03:27:00
1. 题目 给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到: i + x ,其中 i + x < arr.length 且 0 < x <= d 。 i - x ,其中 i - x >= 0 且 0 < x <= d 。 除此以外,你从下标 i 跳到下标 j 需要满足: arr[i] > arr[j] 且 arr[i] > arr[k] ,其中下标 k 是 所有 i 到 j 之间的数字(更正式的, min(i, j) < k < max(i, j) )。 你可以选择数组的 任意 下标开始跳跃。请你返回你 最多 可以访问多少个下标。 请注意,任何时刻你都不能跳到数组的外面。 示例 1: 输入:arr = [ 6 , 4 , 14 , 6 , 8 , 13 , 9 , 7 , 10 , 6 , 12 ] , d = 2 输出: 4 解释:你可以从下标 10 出发,然后如上图依次经过 10 -- > 8 -- > 6 -- > 7 。 注意,如果你从下标 6 开始,你只能跳到下标 7 处。你不能跳到下标 5 处因为 13 > 9 。 你也不能跳到下标 4 处,因为下标 5 在下标 4 和 6 之间且 13 > 9 。 类似的,你不能从下标 3 处跳到下标 2 或者下标 1 处。 示例 2 : 输入:arr = [ 3 , 3 , 3 , 3 , 3 ] , d

「JSOI2014」支线剧情2

北城以北 提交于 2020-02-02 22:47:18
「JSOI2014」支线剧情2 传送门 不难发现原图是一个以 \(1\) 为根的有根树,所以我们考虑树形 \(\text{DP}\) 。 设 \(f_i\) 表示暴力地走完以 \(i\) 为根的子树的最小代价,那么 \(f_i\) 的计算就很显然了: \[f_i = \sum_{j \in son_i}f_j + s_j \times dis(i, j)\] \(s_i\) 表示以 \(i\) 为根的子树的叶子数。 我们再设一个 \(dp_i\) 表示在可以存档读档的条件下走完以 \(i\) 为根的子树的最小代价。 那么我们的转移就是枚举 \(i\) 的一个儿子用来存档或者不存档,然后计算 \(dp_i\) 即可。 参考代码: #include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout) template < class T > inline T min(T a, T b) { return a < b ? a : b; } template < class T > inline void read(T& s) { s = 0; int f = 0; char c = getchar(); while ('0' > c

NOIP2018 摆渡车

馋奶兔 提交于 2020-02-01 21:16:03
摆渡车 定义,无比重要 题意 显然的,我们有一个dp的想法,类似于递降子序列的想法 我们显然的,这是一个一维dp,所以,我们定义 \(f[i]\) 函数,为 \(0\) \(-i\) 的时间内,所出现顾客的等待时间的最小值 但是,有问题,这样的状态,没有dp转移方程。。。。。因为,状态描述不清,你有一个发车间隔为 \(m\) 所以我们吧 \(dp\) 的状态强化,为 \(dp[i]\) ,表示在 \(i\) 时刻发车 \(0-i\) 时出现的乘客等待时间的的最小值 这样我们就把 \(dp\) 的状态描述清楚了我们再来推 \(dp\) 的转移方程 \[ \cal f_i= \begin{cases} Min_{j=1}^i\{f_j+\sum_{j<t_k\leq i}i-t_k\} &i\ge m\\ \sum _{t_i<=i} (i-t_k)&i<m \end{cases} \] 我们照着这个直接抄就好了 需要注意的是,我们在这里要做一个前缀和,让转移的复杂度降下来,但那也是 \(O(n^2)\) 的会超时 不妨,我们即令 \(cnt_i\) , \(0-i\) 中出现的人数,而 \(sum_i\) ,为其出现时间 \(t_k\) 之和 \(50pts\) #include <iostream> #include <cstdio> #include <cstring>

[题解]超级教主-dp

房东的猫 提交于 2020-02-01 13:25:35
超级教主 描述 教主很能跳,因为Orz他的人太多了。教主跳需要消耗能量,每跳1米就会消耗1点能量, 如果教主有很多能量就能跳很高。 教主为了收集能量,来到了一个神秘的地方,这个地方凡人是进不来的。在这里,教主 的正上方每100米处就有一个能量球(也就是这些能量球位于海拔100,200,300……米 处),每个能量球所能提供的能量是不同的,一共有N个能量球(也就是最后一个能量 球在N×100米处)。教主为了想收集能量,想跳着吃完所有的能量球。教主可以自由控 制他每次跳的高度,接着他跳起把这个高度以下的能量球都吃了,他便能获得能量球内 的能量,接着吃到的能量球消失。教主不会轻功,教主不会二段跳,所以教主不能因新 吃到的能量而变化此次跳跃的高度。并且教主还是生活在地球上的,所以教主每次跳完 都会掉下来。 问教主若要吃完所有的能量球,最多还能保留多少能量。 输入 输入的第1行包含两个正整数N,M,表示了能量球的个数和教主的初始能量。 第2行包含N个非负整数,从左到右第I个数字依次从下向上描述了位于I×100米位置能量 球包含的能量,整数之间用空格隔开。 输出 输出仅包括一个非负整数,为教主吃完所有能量球后最多保留的能量。 输入样例 1 3 200 200 200 200 输出样例 1 400 数据范围补充: 先考虑部分数据 考试的时候只想到这样了 \(b[i]\) 数组完成前缀和,表示前