dp

USACO 2019 January Contest Platinum T1: Redistricting

匿名 (未验证) 提交于 2019-12-03 00:44:02
题目大意 奶牛们的特大城市,牛都,要进行重新分区了!――这总是一个在居住在这里的两大主要种族(荷斯坦牛和更赛牛)之间富有争议的政治事件,因为两大种族都想要在牛都政府中保持足够的影响力。 牛都的大都市圈由一列N块牧草地(1≤N≤3*1e5)组成,每块里有一头奶牛,均为荷斯坦牛和更赛牛之一。 牛都政府想要将大都市圈划分为若干个连续的区,使得每个区至多包含K块牧草地(1≤K≤N),并且每块牧草地恰好属于一个区。由于政府当前由荷斯坦牛控制,她们想要找到一种分区方式能够最小化更赛牛较多或者均势的区的数量(如果更赛牛的数量与荷斯坦牛的数量相等那么这个区就是均势的)。 有一个关心政治的更赛牛团体想要知道政府的分区计划可能会对她们造成多少损害。帮助她们求出最坏情况,也就是更赛牛较多或是均势的区的最小可能的数量。 题目分析 看完题目,我们可以明显得到一个 O(NK) 的dp。 令 dp[i] 表示 1~i 中G牛较多或是均势的区的最小可能的数量。sum[i]表示 1~i 中H牛的数量减去G牛的数量。 显然 dp[i] = min( dp[i-j] + (sum[i]-sum[j])<=0?1:0 , dp[i] )。 考虑如何优化dp。 发现,dp[i]的值仅与 dp[i-k+1] ~ dp[i-1] 的值有关,所以我们会想到用单调队列优化dp。 单调队列(小根堆)中存两个值,分别为 位置x 与

BZOJ2002 弹飞绵羊

匿名 (未验证) 提交于 2019-12-03 00:43:02
title: BZOJ2002 弹飞绵羊 date: 2018-07-20 19:39:51 tags: 分块 --- 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。 就不能想一个好点的背景吗? ˼· 很好的想法题,一开始并没有看出来和分块有半毛钱关系。。。 经过WangZY dalao的指点后,知道了要记录本块的绵羊要花多少步跳到下一块,以及跳到下一块的坐标是什么。 深究其原因,我们是牺牲了query的时间来换取了修改的时间,由此避免修改时“牵一发而动全身”,平衡query和修改的时间(这本身也是分块的作用) #include<bits/stdc++.h> #define M 200005 using namespace std; struct node{ int to;//到哪一个块 int step;//需要多少步 }dp[M]; int n,m,s;//块的大小 int

windy数(数位dp)

匿名 (未验证) 提交于 2019-12-03 00:42:01
传送门 #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #define maxn 20 long long dp[20][10];//dp[i][j]表示前面一个数为j的i位数的方案数 int bit[20]; long long dfs(int pos,int pre,int f,int lim) //pos当前枚举到的位置,pre记录pos位置前一个位置的数,因为当枚举到pos然后无前导0的时候要拿判断i和前一个数即pre的差是否>=2,如果f为1,即枚举第pos位数时有前导0,此时pre是无意义的。 { int newf,i;//newf用来记录枚举pos-1位置时有没有前导0 int up=lim?bit[pos]:9; if(pos==0) return 1; if(!lim&&(f==0)&&(dp[pos][pre]!=-1)) return dp[pos][pre]; long long ans=0; for(i=0;i<=up;i++) { if(f==1&&i==0) newf=1; else if(f!=1) newf=0; else if(f==1&&i!=0) newf=0; if(f==1)//有前导0的话,pre无效,pow位置的数可以在0~up随便取 {

小a和uim之大逃离(dp)

匿名 (未验证) 提交于 2019-12-03 00:41:02
题目背景 小a和uim来到雨林中探险。突然一阵北风吹来,一片乌云从北部天边急涌过来,还伴着一道道闪电,一阵阵雷声。刹那间,狂风大作,乌云布满了天空,紧接着豆大的雨点从天空中打落下来,只见前方出现了一个披头散发、青面獠牙的怪物,低沉着声音说:“呵呵,既然你们来到这,只能活下来一个!”。小a和他的小伙伴都惊呆了! 题目描述 瞬间,地面上出现了一个n*m的巨幅矩阵,矩阵的每个格子上有一坨0~k不等量的魔液。怪物各给了小a和uim一个魔瓶,说道,你们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,并且要求最后一步必须由uim吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。怪物还说道,最后谁的魔瓶装的魔液多,谁就能活下来。小a和uim感情深厚,情同手足,怎能忍心让小伙伴离自己而去呢?沉默片刻,小a灵机一动,如果他俩的魔瓶中魔液一样多,不就都能活下来了吗?小a和他的小伙伴都笑呆了! 现在他想知道他们都能活下来有多少种方法。 输入输出格式 输入格式: 第一行,三个空格隔开的整数n,m,k 接下来n行,m列,表示矩阵每一个的魔液量。同一行的数字用空格隔开。 输出格式: 一个整数,表示方法数。由于可能很大,输出对1 000 000 007取余后的结果。

洛谷 P1858 多人背包 解题报告

匿名 (未验证) 提交于 2019-12-03 00:40:02
求01背包前k优解的价值和 第一行三个数 \(K\) 、 \(V\) 、 \(N\) 接下来每行两个数,表示体积和价值 前k优解的价值和 对于100%的数据,$ K\le 50,V\le 5000,N\le 200$ 算是积累见识吧,有些类型的题不见过一面估计比较难想 方程为 \(dp[i][j][k]\) 代表前 \(i\) 中在装了 \(j\) 时第 \(k\) 优值 如何转移呢 对 \(dp[i][j]\) 来说,由 \(dp[i-1][j]\) 和 \(dp[i-1][j-w]+c\) 转移 即我们从 \(dp[i-1][j][1...k]\) 和 \(dp[i-1][j-w][1...k]+c\) 中选出前 \(k\) 大的给 \(dp[i][j][1...k]\) 用到了归并排序的思想 Code: #include <cstdio> #include <cstring> int max ( int x , int y ){ return x > y ? x : y ;} int min ( int x , int y ){ return x < y ? x : y ;} const int inf = 0x3f3f3f3f ; int k , v , n , dp [ 52 ][ 5010 ], c , w , tmp [ 52 ]; int main () {

DP之字符串

匿名 (未验证) 提交于 2019-12-03 00:36:02
Problem1 给定一个字符串,问分割成最少的子串,是每个子串均为回文串。 状态转移方程 : dp[j] = min(dp[j], dp[i - 1] + 1); 具体: for ( int j = 1 ; j <= len; j++) { //枚举长度,因为6这个长度的结果是可以用5推过来的。 for ( int i = j - 1 ; i >= 1 ; i--) { //枚举当前长度的断开点 if ( is [j][i] && dp[i] > dp[j - 1 ] + 1 ) { //is为[i, j]是否是回文串 dp[i] = dp[j - 1 ] + 1 ; } } } 为什么不需要二维数组,因为我们根本不需要知道dp[i][j]的状态,这种的题目,可以手动模拟字母一个个加上去之后dp[j]的变化,便可以推出结论来。 Problem2 求字符串有多少回文子序列。(这里的子序列可以不连续) 状态转移方程: dp[j][i] = (dp[j + 1][i] + dp[j][i - 1] - dp[j + 1][i - 1] + mod) % mod; //小的容斥 if(str[i] == str[j]) dp[j][i] = (dp[j][i] + dp[j + 1][i - 1] + 1) % mod; 具体: for ( int i = 1 ; i < len; i+

Codeforces Round #490(Div.3) F

匿名 (未验证) 提交于 2019-12-03 00:34:01
n个人,每个人有一个lucky number,每个人抽k张卡片。 一个人如果抽到的卡片中有t个lucky number,这个人的价值为h[t]。 求最大的价值和。 只需考虑带有lucky number的卡片,因为其他不是某个人的lucky number的卡片不会影响最后的价值。 不同的lucky number是不会相互影响的。因为如果把某个人lucky number放到另一个lucky number不一样的人那里,只会降低最后的总价值。h是升序的。 所以只需考虑有相同lucky number的人群中怎么分配带有他们的lucky number的卡片。而且不用在dp方程中加入lucky number,因为都是一样的,即与lucky number无关。 令dp[x][y]为x个lucky number(记为q)相同的人,分配y张带有q的卡片的最大价值。则 \(dp[x+1][y+i]=max\{dp[x][y]+h[i],0<=i<=k\}\) ,则最后的总价值为 \(\mathit{ans} = \sum\limits_{i = 1}^{10^5}\mathit{dp}[f_i][c_i]\) #include < bits / stdc ++. h > #define REP ( i , a , b ) for ( int i =( a ); i <( b ); i ++)

leetcode 最大子序和

匿名 (未验证) 提交于 2019-12-03 00:21:02
状态:dp[i]表示以第i个元素结尾的连续子数组的最大和 状态转移方程: dp[i] = max( 0, dp[i-1] ) + nums[i]; #include <vector> using namespace std; class Solution { public: int maxSubArray(vector<int>& nums) { int n = nums.size(); vector<int> dp(n+1,0); if( nums[0] > 0 ) dp[0] = nums[0]; else dp[0] = 0; for( int i = 1; i < n; i++ ) { dp[i] = max( 0, dp[i-1] ) + nums[i]; } int ans = dp[0]; for( int i = 0; i < n; i++ ) ans = min( ans, dp[i] ); return ans; } }; 文章来源: leetcode 最大子序和

繁繁的游戏

匿名 (未验证) 提交于 2019-12-03 00:17:01
繁繁想和小伙伴们打游戏,游戏在一个山庄进行,这个山庄有N座山,编号为1到N,为了方便大家在不同的山之间移动,繁繁建了一些桥,由于技术的原因,桥连接的两座山的高度差不能超过d,现在已知这些桥,求这个山庄最高的山和最低的山差距最大是多少?数据保证所有山之间都是联通的。 第一个一个数T,表示测试数据数量(T<=5,2<=N<=50,0<=d<=1000) 每组数据第一行两个数N和d 接下来一个N行N列的矩阵,第i行j列为Y表示i和j之间建了一座桥,否则表示没有建保证第i行j列和第j行i列值相同,并且第i行第i列值为N T行,每行一个答案,若最大值可能为正无穷,输出-1 3 3 10 NYN YNY NYN 2 1 NN NN 6 1000 NNYNNN NNYNNN YYNYNN NNYNYY NNNYNN NNNYNN 20 -1 3000 第一个样例,1和2之间不能超过d,2和3之间不能超过d,那么最大就是1和2差恰好为d,2和3差恰好为d 对于20%的数据,T<=3,N<=40 对于50%的数据,T<=3 对于100%的数据,T<=5,2<=N<=50,0<=d<=1000 //#pragma GCC optimize(3) #include<iostream> #include<cstdio> #include<algorithm> #include<cstring>