dp

LIS最长上升子序列

妖精的绣舞 提交于 2019-11-28 16:23:07
题意:有一个长为n的数列,求出这个序列中最长的上升子序列长度(不连续,不能等于)。 解法1:简单dp(n 2 ) 思路: 状态设计:F [ i ] 代表以 A [ i ] 结尾的 LIS 的长度 状态转移:F [ i ] = max { F [ j ] + 1 ,F [ i ] } (1 <= j < i,A[ j ] < A[ i ]) 边界处理:F [ i ] = 1 (1 <= i <= n) 1 const int maxn = 103, INF = 0x7f7f7f7f; 2 int a[maxn], f[maxn]; 3 int n,ans = -INF; 4 int main() 5 { 6 scanf("%d", &n); 7 for(int i=1; i<=n; i++) 8 { 9 scanf("%d", &a[i]); 10 f[i] = 1; 11 } 12 for(int i=1; i<=n; i++) 13 for(int j=1; j<i; j++) 14 if(a[j] < a[i]) 15 f[i] = max(f[i], f[j]+1); 16 for(int i=1; i<=n; i++) 17 ans = max(ans, f[i]); 18 printf("%d\n", ans); 19 return 0; 20 } 解法2:贪心优化

lightoj 1038 Race to 1 Again 期望

十年热恋 提交于 2019-11-28 14:40:41
dp[i]表示从i到1的期望次数。 dp[i] = ∑dp[j] / cnt + 1。(cnt为所有因子数量,含1和i)但是∑dp[j]中有一个dp[i]。把dp[i]都移项到左侧,得dp[i] = (∑dp[j] - dp[i] + cnt) / (cnt - 1)。提前预处理出来,O(1)回答即可。 1 #include <cstdio> 2 #include <cmath> 3 using namespace std; 4 double dp[100100]; 5 int n,T,cas; 6 int main() 7 { 8 dp[1] = 0; 9 for (int i = 2;i <= 100000;i++) 10 { 11 int t = sqrt(i),cnt = 2; 12 double sum = 0; 13 for (int j = 2;j <= t;j++) 14 if (i % j == 0) 15 { 16 cnt++; 17 sum += dp[j]; 18 if (i / j != j) 19 { 20 cnt++; 21 sum += dp[i / j]; 22 } 23 } 24 dp[i] = (sum + cnt) / (cnt - 1); 25 } 26 for (scanf("%d",&T);T != 0;T--) 27 { 28 cas

[leetcode]Python实现-746.使用最小花费爬楼梯

和自甴很熟 提交于 2019-11-28 13:48:50
746.使用最小花费爬楼梯 描述 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost i 。 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。 您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。 示例 输入: cost = [10, 15, 20] 输出: 15 解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。 输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 输出: 6 解释: 最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。 注意 cost 的长度将会在 [2, 1000]。 每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999]。 思路:动态规划。求到达每一阶的最小成本。倒数第一和倒数第二的最小值即为解。 我是这么考虑的:把问题缩小,只有两种办法到达第i阶,一种是i-2阶走两步到达,一种是i-1阶走一步到达。题目中说出发点可以任选cost[0]或cost[1],这里可能稍微有些干扰,会误以为要按照两个初始点分别计算。比如到达cost[2]的方法: - cost[1]走一步 - cost[0]走两步 - cost[0]走两个一步

NC50 E

烈酒焚心 提交于 2019-11-28 10:28:10
这什么垃圾数据一堆贪心的我随手就能卡掉。 我们考虑dp 先考虑有多少段叭,然后考虑每一段是不是0, 然后就得到递推式 如果当前串是0 dp[i][0]=dp[i-1][0]+dp[i-1][1],//我们把这个0拿出来,与前面所有的方案都形成一种新方案 dp[i][1]=dp[i-1][1];//直接拼上去 如果不是0 dp[i][0]=0; dp[i][1]=dp[i-1][1]*2+dp[i-1][0];//对于dp[i-1][1]来说拼或者不拼,对于dp[i-1][0]来说只能不拼。 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 998244353; int n;string s; bool ning[100005];int cnt=0; ll dp[100005][2]; int main(){ ios::sync_with_stdio(false); cin>>n>>s;s="*"+s; int tmp=0,len=0; for(int i=1;i<=n;i++){ tmp=(tmp+s[i]-'0')%3; len++; if(!tmp){ ning[++cnt]=(len==1&&s[i]=='0'); len=0; } } if(tmp)cout<

dp

走远了吗. 提交于 2019-11-28 05:31:23
codeforces 4D 题意:给定n和信封和一个w 和 h,要求以下的信封选取最多的,然后 wi 必须比 w 大并递增,hi 比 h 大也递增,问最多的信封数和哪些,按照顺序输出 题解:按照w递增排序后,求h的最长上升子序列并输出路径 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<cstdlib> #include<queue> #include<set> #include<string.h> #include<vector> #include<deque> #include<map> using namespace std; #define INF 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define eps 1e-4 #define bug printf("*********\n") #define debug(x) cout<<#x"=["<<x<<"]" <<endl #define ll long long #define LL long long const int MAXN = 1e5 + 5; const int mod =

D1. Kirk and a Binary String (easy version)

◇◆丶佛笑我妖孽 提交于 2019-11-28 02:43:14
D1. Kirk and a Binary String (easy version) 01串找最长不降子序列 给定字符串s,要求生成一个等长字符串t,使得任意l到r位置的最长不降子序列长度一致 从后往前暴力枚举,枚举每个一替换成0后是否改变了l到r位置的最长不降子序列长度 01串的最长不降子序列,可以通过线性dp求解 dp i表示以i结尾的最长不降子序列长度 dp[0]=dp[0]+s[i]=='0'; dp[1]=max(dp[0],dp[1])+s[i]=='1'; #include<bits/stdc++.h> using namespace std; #define int long long #define sc(x) scanf("%I64d",&(x)); typedef long long ll; #define maxn 2005 #define INF 1e18 ll N; ll val[2][maxn]; ll dp[2]; void LIS(string s,int st,int val[]) { dp[0]=dp[1]=0; for(int i=st;i<N;i++){ if(s[i]=='0'){ dp[0]++; }else dp[1]=max(dp[0],dp[1])+1; val[i]=max(dp[0],dp[1]); } } signed

C. Ilya And The Tree 树形dp 暴力

末鹿安然 提交于 2019-11-28 00:10:51
C. Ilya And The Tree 写法还是比较容易想到,但是这么暴力的写法不是那么的敢写。 就直接枚举了每一个点上面的点的所有的情况,对于这个点不放进去特判一下,然后排序去重提高效率。 注意dp[v]一开始存的是从根节点到这个节点都选的情况,这样才好往后转移。 #include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <cstring> #define inf 0x3f3f3f3f using namespace std; const int maxn = 4e5 + 10; typedef long long ll; int dp[maxn], head[maxn], cnt = 0, a[maxn]; vector<int>vec[maxn]; struct node { int u, v, nxt; node(int u=0,int v=0,int nxt=0):u(u),v(v),nxt(nxt){} }ex[maxn]; void init() { memset(head, -1, sizeof(head)); cnt = 0; } void add(int u,int v) { ex[cnt] = node(u, v, head[u]); head

@codeforces - 913F@ Strongly Connected Tournament

流过昼夜 提交于 2019-11-28 00:07:07
目录 @description@ @solution@ @accepted code@ @details@ @description@ n 个选手参加了一场竞赛,这场竞赛的规则如下: 1.一开始,所有选手两两之间独立进行比赛(没有平局)。 2.主办方将胜者向败者连边形成 n 个点的竞赛图。 3.主办方对这个竞赛图进行强连通分量缩点。 4.每一个强连通分量内部的选手重复步骤 1~3,直到每一个强连通分量内只剩一个选手。 现已知当 i < j 时,选手 i 战胜选手 j 的概率是 p,请计算比赛次数的期望。 Input ‘ 第一行包含一个整数 n (2 ≤ n ≤ 2000) — 表示玩家个数。 第二行包含两个整数 a 和 b (1 ≤ a < b ≤ 100) — 表示概率 p = a/b。 Output 输出一行一个整数表示期望,对 998244353 取模。 Examples Input 3 1 2 Output 4 Input 3 4 6 Output 142606340 Input 4 1 2 Output 598946623 Note 第一组样例答案是 4; 第二组样例答案是 27/7; 第三组样例答案是 56/5。 @solution@ 可以发现题目给定的过程其实就是个求解子问题的过程,可以使用 dp。 考虑最暴力的解法:枚举每条边的定向,计算概率与此时的强连通分量,进行

征途堆积出友情的永恒「堆优化dp」

℡╲_俬逩灬. 提交于 2019-11-27 21:31:47
直接写题解: 很简单的dp暴力转移式子:f[i]=MAX{f[j]+max(tax[j],sum[i]-sum[j])} 观察式子,只有一个变量sum[i]; 而其他都为定量; 则考虑维护 两个定量:f[j]+tax[j] || f[j]-sum[j] 而要找耗费最小;考虑用堆维护一个量; 注意是一个量; 为什么不是两个量? 想想,你在dp式子中取的max;不是取tax[j]就是取deta(sum); 那就是说如果你使一个量主动;那么另一个量就是被动的,、由你确定的这个量决定的 所以就维护tax[j]+f[j]; 按大小排序;然后取最优值; 设 pay=q.top.w; (tax[j]+f[j]) 若pay>=f[j]-sum[j]+sum[i];那就用它呗,反正是合法的; 若pay<f[j]-sum[j]+sum[i] 那这种方案就不合法;那就把他的被动决策塞入另一个堆中维护; 那么会形成两个堆,两个堆中的状态都是合法的,然后直接取堆顶元素就是最优的; 而可能你会想到那第一个堆中的元素pop掉了,会不会有后效性; 其实不会;因为sum[i]-sum[j] 的sum[j]固定而sum[i]递增; 所以当他从1pop出去后,他在2中就会一直呆着了; 总结: 1.对于这种dp优化,若dp式子中出现变量很少而定量很多,就要考虑到维护定量; 2.而对于dp式子中有max(),min(

DP

巧了我就是萌 提交于 2019-11-27 18:47:34
简单理解: 就是一层推倒下一层 (每一层最优) 代码格式 return { xxx(dp(),dp()}; for() dp【】=xxx(dp(),dp(); 来源: https://www.cnblogs.com/Lamboofhome/p/11372947.html