dp

霸气de小男生 提交于 2020-01-17 19:26:39
------------恢复内容开始------------ ///一道简单dp,题意:让你求出给出数列中加起来可以整出 m的方案数 ///一道简单dp,题意:让你求出给出数列中加起来可以整出 m的方案数 ///dp【i】【j】表示前i个中你挑选n个(1<=n<=i)余数为j的方案数 ///所以转移方程为 dp[i - 1][j]未有i时的方案数加上 dp[i - 1][(j + f - a[i] % f) % f]即将加上i(所以得减去a【i】)这样+a[i]才有j #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a) memset(a, 0, sizeof(a)) typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db

RMQ之ST求区间最大值

浪子不回头ぞ 提交于 2020-01-16 20:33:00
题目链接: https://cn.vjudge.net/problem/HRBUST-1188 每一次按照二进制的方式进行更新,二维数组dp [i] [j],i表示下标,j表示从i 开始的往后移动2的j-1次方个数再-1. AC代码: 1 #include<iostream> 2 #include<cmath> 3 #include<stack> 4 #include<iomanip> 5 #include<queue> 6 #include<cstring> 7 #include<string> 8 #include<stdio.h> 9 #include<algorithm> 10 #include<vector> 11 using namespace std; 12 # define inf 0x3f3f3f3f 13 # define ll long long 14 const int maxn = 50000+100; 15 int dp[maxn][20]; 16 int n; 17 void RMQ() 18 { 19 for(int i=1; i<=20; i++) 20 { 21 for(int j=1; j<=n; j++) 22 { 23 if(j+(1<<i)-1<=n) 24 { 25 dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i

染色问题 状态dp

血红的双手。 提交于 2020-01-16 14:24:24
给你一个图,要求用最少的颜色染这个图,使得这个图任意直接相连的点颜色不一样! 思路: 典型的状压dp–图的染色问题! 令dp[s] 为染 s 这个状态图 最小的颜色数,其中 s 里 1代表要染色的 0 代表不需要染色! 那么显然dp[0] = 0 dp[s] = min{dp[s^s0] + 1} 其中s0是s 的子集并且 里面的1 在图中不直接相连! 判断 状态s 里面的1 是否不直接相连可以预处理! 找s 的子集 可以减1 进行&运算! (想一想就知道) 原文链接:https://blog.csdn.net/aozil_yang/article/details/52927568 # include <cstdio> # include <cstring> # include <algorithm> # define min(a,b) (a) > (b) ? (b) : (a) using namespace std ; const int maxn = 19 ; typedef long long ll ; const ll mod = 1ll << 32 ; const int inf = 0x3f3f3f3f ; int n ; char g [ maxn ] [ maxn ] ; bool ok [ 1 << maxn ] ; int dp [ 1 << maxn ] ;

一维消消乐(DP)

青春壹個敷衍的年華 提交于 2020-01-16 13:37:56
一维消消乐是一款非常简单的游戏。有n颗珠子排成一排,每一颗珠子有一个价值w(可能是负数)。 游戏是这样,你可以选择如若干对相邻的珠子,让他们同时消去。每一对珠子的消失,都会使得总分数加上两颗珠子相乘的分数。 注意,每个珠子只能消一次,并且珠子消去以后,还会占位。 输入格式 输入第一行一个整数n(1≤n≤10000)。 接下来一行输入n个整数w i (-1000≤w i ≤1000)。 输出格式 输出最大的分数。 样例输入 8 -9 -5 -4 -2 4 -5 -4 2 样例输出 73 用dp[i][0]表示前i数,第i个数没有和前面的数组合的最大值。 用dp[i][1]表示前i个数,第i个数已经和前面的数组合的最大值。 那么 dp[i][0]=max(dp[i-1][0],dp[i-1][1]) dp[i][1]=dp[i-1][0]+w[i-1]*w[i] 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include

POJ 2955 Brackets 区间dp

心已入冬 提交于 2020-01-14 13:19:50
http://poj.org/problem?id=2955 区间dp的写法还是dfs的好写。 设dp[i][j]表示[i, j]这个区间的合法情况的最大值。 然后想要求[i, j]合法情况的最大值,有两种。 1、如果i和j的搭配的括号,那么dp[i][j] = dp[i + 1][j - 1] + 2; 2、同时还可能是分开区间,合并后才更大,例如:()() dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]); #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset>

HDU1024

时间秒杀一切 提交于 2020-01-14 01:39:55
kuangbin带你飞系列 简单dp A HDU 1024 题意:把一个有n个数的序列,分成不相交的m块,求这m块的和。 思路: 参考此博主后得 假设当前数为第i个,该数有2种可能: 第一种是第i个数接入上一个的那一块中,dp[i] [j]=dp[i] [j-1] +all[i] ; 第二种是第i个数作为新的一块。dp[i] [j] = 前i个数中构成j-1块的最大和+all[i]。 得到代码 #include<bits/stdc++.h> using namespace std; const int inf=1e9; const int max_n=1e6+10; const int max_m=100; int all[max_n]; int dp[max_m][max_n]; int main(void) { int m,n; while(scanf("%d %d",&m,&n)!=EOF) { all[0]=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;++i){scanf("%d",&all[i]);} for(int i=1;i<=m;++i) //计算分成i块 for(int j=i;j<=n;++j) //把前j个分成i块 { dp[i][j]=dp[i][j-1]+all[j]; //第一种情况是:前j-1个已经分为i块

数位DP-数字游戏

半腔热情 提交于 2020-01-13 17:12:40
数字游戏 科协里最近很流行数字游戏。 某人命名了一种不降数,这种数字必须满足从左到右各位数字呈非下降关系,如 123,446。 现在大家决定玩一个游戏,指定一个整数闭区间 [a,b],问这个区间内有多少个不降数。 输入格式 输入包含多组测试数据。 每组数据占一行,包含两个整数 a 和 b。 输出格式 每行给出一组测试数据的答案,即 [a,b] 之间有多少不降数。 数据范围 1≤a≤b≤231−1 输入样例: 1 9 1 19 输出样例: 9 18 题解: 利用类似前缀和的思想 [a, b]范围满足要求的数=[0,b]范围满足要求的数 - [0,a-1]范围满足要求的数 所以我们可以封装求[0, x]满足要求的数字为一个函数即可 一个数字x, 最右边当成第一位,数字长度为len的话,最左侧就为第len位,把他们存储到a数组中。 从最左侧开始搜索, pos记录枚举哪一位了, 需要记录前一位数字pre,pre如果比当前枚举的数字i大的话,就continue不予统计。 需要用一个limit记录当前位能枚举的上界,比如19 这个2位数,最左侧一位能枚举的范围是0-1, 不能超过1, 如果limit为false当前位能枚举到9,否则只能到最大a[pos] dfs的含义就是从左往右枚举每一位,看是否符合要求。 为了优化,记忆化即可,需要注意有limit的情形不能用记忆化,比如求

POJ 2955 Brackets 区间dp

杀马特。学长 韩版系。学妹 提交于 2020-01-13 12:04:44
按照合法匹配条件,找最大的匹配 一眼就是区间dp 也知道dp[i][j]表示i-j中最大的匹配 但是状态转移方程怎么写呢?? 其实对于这个题,感觉有很多种写法,看过网上的各种各样的题解,强烈Orz~ 思路: 还是倒着dp,更新dp[i][j],有两种情况 1:当前字符不在最佳匹配中,dp[i][j]=dp[i+1][j]; 2:当前字符在最佳匹配中,dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+1][j]+2),前提条件是i位置和k位置匹配成功 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; typedef long long LL; int dp[105][105]; char s[105]; int main() { while(~scanf("%s",s+1)) { if(s[1]=='e')break; int n=strlen(s+1); memset(dp,0,sizeof(dp)); for(int i=n-1;i>=1;--i) { for(int j=i+1;j<=n;++j) { dp[i][j]=dp[i+1][j];

96. 不同的二叉搜索树

只愿长相守 提交于 2020-01-12 00:55:55
给定一个整数 n ,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3思路:根节点有左子树和右子树,n个节点的二叉树除去根节点还有n-1个节点,左子树和右子树一共n-1个节点,左子树和右子树的数量可以是(0,n-1),(1,n-2)...(n-1,0);   假设m个节点的二叉树有f(m)种,则总共种类数=[f(0)*f(n-1)]+[f(1)*f(n-2)]+...+[f(n-1)*f(0)] func numTrees(n int) int { dp:=make([]int,n+1) dp[0],dp[1]=1,1 for i:=2;i<=n;i++{ dp[i]=0 for j:=1;j<=i;j++{ dp[i]=dp[i]+dp[j-1]*dp[i-j] } } return dp[n] } 来源: https://www.cnblogs.com/fwdqxl/p/9353667.html

LeetCode--322:零钱兑换(java)

早过忘川 提交于 2020-01-11 15:40:05
原题链接 思路:动态规划 状态定义 dp[i]:表示兑换 i 元需要的最少钱币数 dp方程:dp[i] = min{ dp [ i - coins[ j ]] } + 1(+1表示我自己需要使用一张,j 是遍历 coins 数组的下标) public int coinChange ( int [ ] coins , int amount ) { //coins = [1,2,5,7,10] 金额14 int [ ] dp = new int [ amount + 1 ] ; for ( int i = 0 ; i <= amount ; i ++ ) { dp [ i ] = - 1 ; //最初所有金额的最优解均为-1(不可到达) } //dp = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] dp [ 0 ] = 0 ; //金额0 的最优解为0 //dp = [0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] for ( int i = 1 ; i <= amount ; i ++ ) { //循环各个面值,找到dp[i]的最优解 for ( int j = 0 ; j < coins . length ; j ++ ) { //如果兑换总额 >= 当前钱币面额 并且