UVA 10003 区间DP】的更多相关文章

区间dp,可以以一个区间为状态,f[i][j]是第i个切点到第j个切点的木棍的最小费用 那么对于当前这一个区间,枚举切点k, 可以得出f[i][j] = min{dp(i, k) + dp(k, j) | i < k < j} + a[j] - a[i](这一段的长度,也就是这一刀的费用) 然后记住要人为的加入两个切点头和尾 然后因为长区间依赖于短区间,所以要从短区间渐渐推到长区间. 如果是记忆化搜索,那么就是左端点和右端点不断减少,递归,满足. 如果是递推,那么注意区间长度要不断变长,具体看…
这个题目蛮有新意的,一度导致我没看透他是区间DP 给一个0-L长度的木板,然后给N个数,表示0-L之间的某个刻度,最后要用刀把每个刻度都切一下 使其断开,然后每次分裂的cost是分裂前的木板的长度.求整个分开之后的最小cost. 当时下意识就想到类似花瓶插花问题,即dp[i][j],表示第i个事物放在第j次动作来的最小代价,但是当我写起来发现很麻烦,我是以刻度点来表示的i,结果发现处理起来相当麻烦,因为实体实际是一块一块的小木板,以点作为转移变量 不仅要加诸多限制,而且加完后发现会互相矛盾,原因…
题意: 给一段字符串成段染色,问染成目标串最少次数. SOL: 区间DP... DP[i][j]表示从i染到j最小代价 转移:dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]); CODE: BZ: /*================================================================= # Created time: 2016-03-28 21:10 # Filename: uva4394.cpp # Desc…
uva 紫书例题,这个区间dp最容易错的应该是(S)这种匹配情况,如果不是题目中给了提示我就忽略了,只想着左右分割忘记了这种特殊的例子. dp[i][j]=MIN{dp[i+1][j-1] | if(match(i,j) , dp[i][k]+dp[k+1][j] | i<=k<=j .}注意初始化dp[i][i]=1,表示1个字符最少需要一个才能匹配,dp[i+1][i]=0,因为可能只有两个字符使得i+1>j-1,我们可以认为中间是空字符已经匹配了. 打印路径利用了递归,很巧妙,lr…
https://vjudge.net/problem/UVA-10891 给定一个序列x,A和B依次取数,规则是每次只能从头或者尾部取走若干个数,A和B采取的策略使得自己取出的数尽量和最大,A是先手,求最后A-B的得分. 令 f(i,j)表示对于[i,j]对应的序列,先手可以从中获得的最大得分,那么答案可以写为  f(i,j)-(sum(i,j)-f(i,j)),也就是 2*f(i,j)-sum(i,j) 下面讨论f(i,j)的写法,显然递归的形式更好表达一些,为了防止重复的计算使用记忆化搜索.…
一个字符串如果能简写,要么是重复多次,按题中的要求简写:要么是左右两个部分分别简写后再拼起来. dp(i, j)表示字串(i, j)所能被简写的最短的字符串. 判断一个字符串是否为周期串以及求出它的周期用的KMP算法. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> using namespace std…
很明显带有博弈的味道.让A-B最大,由于双方都采用最佳策略,在博弈中有一个要求时,让一方的值尽量大.而且由于是序列,所以很容易想到状态dp[i][j],表示序列从i到j.结合博弈中的思想,表示初始状态i->j情况下,先手能获得的最大分数.后手能获得的就是sum[i][j]-dp[i][j].接下来枚举先手选取的是两端的哪一段即可. #include <iostream> #include <cstdio> #include <cstring> using name…
当前区间f(i, j)分两种情况,一种是s[i]于s[j]符合要求,那么可以转移到f[i + 1][j - 1] 这样答案只会更小或者相等 第二种是直接分成两个部分, 即f[i][j] = f[i][k] + f[k + 1][j],这个时候要取min 同时要注意第一种情况未必是最优的,要从一二两种情况里面取最优值 然后输出方面,按照答案反推,如果当前状态刚好等于其中一种情况,那么就递归下去,边界是 一个字符的时候输出两个字符. 另外学会用fgets,不用gets.fgets头文件cstdio,…
题意:对一根长为l的木棒进行切割,给出n个切割点,每次切割的价值,等于需要切割的木头长度. 一开始理解错了,认为切割点时根据当前木条的左端点往右推算. 实际上,左端点始终是不变的一直是0,右端点一直是l,切割点就是在0 ~ l 之间的点,而切割时的价值就是切割这个点的时候当前木条的长度. 状态转移方程:dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j] + cut[j] - cut[i]); 思路就是朝着子区间最优的情况靠拢,然后再求全局最优,由于子结…
题目:uva 10003 Cutting Sticks 题意:给出一根长度 l 的木棍,要截断从某些点,然后截断的花费是当前木棍的长度,求总的最小花费? 分析:典型的区间dp,事实上和石子归并是一样的,花费就是石子的和.那么久不用多说了. AC代码: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include <map> #include <…
UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的长度L,第二行是切割点的个数n,接下来的n行是切割点在木棍上的坐标. 输出切割木棍的最小费用 前话-区间dp简单入门 区间dp的入门下面博客写的非常好,我就是看的他们博客学会的,入门简单,以后的应用就得靠自己了. https://blog.csdn.net/qq_41661809/article/d…
题目连接:10003 - Cutting Sticks 题目大意:给出一个长l的木棍, 再给出n个要求切割的点,每次切割的代价是当前木棍的长度, 现在要求输出最小代价. 解题思路:区间DP, 每次查找当前区间的最优解 , 并记录.需要注意的是输入的切割点并不是从小到大. #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 55; in…
区间dp,切割dp[i][j]的花费和切法无关(无后效性) dp[i][j]表示区间i,j的花费,于是只要枚举切割方法就行了,区间就划分成更小的区间了.O(n^3) 四边形不等式尚待学习 #include<bits/stdc++.h> //变量不要取成ignore left之类 using namespace std; ; int cut[maxn]; int dp[maxn][maxn]; const int INF = 0x3fffffff; int main() { //freopen(…
经典博弈区间DP 题目链接:https://uva.onlinejudge.org/external/108/p10891.pdf 题意: 给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能从一端选取. 并且A B都尽力使自己选择的结果为最大的,可以理解成A B每一步走的都是最优的. 如果A先选择,则A B差值最大是多少. 分析: 总和是一定的,所以一个得分越高,另一个人的得分越低.当前状态总是最开始的状态的一个子状态. d(i,j): 先手取 i ~ j 最优策略下,得分最大值. d…
// 区间DP+next求循环节 uva 6876 // 题意:化简字符串 并表示出来 // 思路:dp[i][j]表示 i到j的最小长度 // 分成两部分 再求一个循环节 #include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <map>…
UVA 10529 - Dumb Bones option=com_onlinejudge&Itemid=8&category=518&page=show_problem&problem=1470" style="">题目链接 题意:你试图把一些多米诺骨牌排成直线,然后推倒它们.可是如果你在放骨牌的时候不小心把刚放的骨牌碰倒了,它就会把相临的一串骨牌全都碰倒.而你的工作也被部分的破坏了. 比方你已经把骨牌摆成了DD__DxDDD_D的形状…
题目传送门 /* 题意:三种操作,插入,删除,替换,问最少操作数使得字符串变成回文串 区间DP:有一道类似的题,有点不同的是可以替换,那么两端点不同的时候可以替换掉一个后成回文, 即dp[j+1][k-1] + 1,还有这道题没有要求打印 */ /************************************************ * Author :Running_Time * Created Time :2015-8-17 15:45:22 * File Name :UVA_10…
题目传送门 /* 题意:问最少插入多少个字符使得字符串变成回文串 区间DP:dp[i][j]表示[l, r]的字符串要成为回文需要插入几个字符串,那么dp[l][r] = dp[l+1][r-1]; (str[l] == str[r]) dp[l][r] = min (dp[l+1][r], dp[l][r-1]) + 1,然后按照状态转移递归输出路径 */ /************************************************ * Author :Running_T…
题目传送门 /* 题意:给一个字符串,连续相同的段落可以合并,gogogo->3(go),问最小表示的长度 区间DP:dp[i][j]表示[i,j]的区间最小表示长度,那么dp[i][j] = min (dp[j][k] + dp[k+1][i+j-1]), digit (i / k) + dp[j][j+k-1] + 2)后者表示可以压缩成k长度连续相同的字符串 4.5 详细解释 */ /************************************************ * Au…
题目传送门 /* 题意:给一个字符串,划分成尽量少的回文串 区间DP:状态转移方程:dp[i] = min (dp[i], dp[j-1] + 1); dp[i] 表示前i个字符划分的最少回文串, 如果s[j] 到 s[i]是回文串,那么可以从dp[j-1] + 1递推过来 */ #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace…
题目链接:http://vjudge.net/problem/viewProblem.action?id=19461 思路:一类经典的博弈类区间dp,我们令dp[l][r]表示玩家A从区间[l, r]得到的最大值,于是就有dp[l][r] = sum[l][r] - min(dp[l + i][r], dp[l][r - i]) (i >= 1 && i + l <= r),最终我们要求的就是dp[1][n] - (sum[1][n] - dp[1][n]). #include…
题目连接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461 Game of sum Description This is a two player game. Initially there are n integer numbers in an array and players A and B getchance to take them alternatively. Each player can take…
题目链接 给n个数, 这n个数的值是从小到大的, 给出个n个数的出现次数. 然后用他们组成一个bst.访问每一个数的代价是这个点的深度*这个点访问的次数. 问你代价最小值是多少. 区间dp的时候, 如果l >= r, 那么返回0, l == r-1, 返回两个数中小的一个. 其他情况的话枚举分界点进行状态转移. #include <bits/stdc++.h> using namespace std; #define mem1(a) memset(a, -1, sizeof(a)) ;…
  Cutting Sticks  You have to cut a wood stick into pieces. The most affordable company, The Analog Cutting Machinery, Inc. (ACM), charges money according to the length of the stick being cut. Their procedure of work requires that they only make one…
https://vjudge.net/problem/UVA-1632 题意: 直线上有n个点,其中第i个点的坐标是xi,且它会在di秒之后消失.Alibaba可以从任意位置出发,求访问完所有点的最短时间. 思路: 区间DP. d[i][j][0]用来表示访问完区间 i ~ j 之间所有点的最短时间,并且此时处于 i 点,相反的,d[i][j][1]表示的是处于 j 点. #include<iostream> #include<string> #include<cstring…
题目链接 设$dp[l][r][p]$为走完区间$[l,r]$,在端点$p$时所需的最短时间($p=0$代表在左端点,$p=1$代表在右端点) 根据题意显然有状态转移方程$\left\{\begin{matrix}dp[l][r][0]=min(dp[l+1][r][0]+x[l+1]-x[l],dp[l+1][r][1]+x[r]-x[l]);\\ dp[l][r][1]=min(dp[l][r-1][0]+x[r]-x[l],dp[l][r-1][1]+x[r]-x[r-1]);\end{m…
区间dp,两个str一起考虑很难转移. 看了别人题解以后才知道是做两次dp. dp1.str1最坏情况下和str2完全不相同,相当于从空白串开始刷. 对于一个区间,有两种刷法,一起刷,或者分开来刷. 规定[i][i-1]为空串,这样一起刷可以归结为第二种情况. 合并的时候,大的区间的次数<=小的区间的,和新加入区间的字符有关. 小的区间是一个字符一个字符的变成大区间的. 所以每次考虑新加入区间的尾部字符j,枚举k划分区间[i][k-1],[k][j]. 要使得刷的次数减少,只有尽量一起刷.比如a…
题目:https://www.luogu.org/problemnew/show/UVA10559 应该想到区间dp.但怎么设计状态? 因为连续的东西有分值,所以应该记录一下连续的有多少个. 只要记录与边界连续的有多少个就能涵盖所有的连续了.只记一边的边界即可. 两个转移:用掉记录的那些连续的 或 在自己区间中再找一个一样颜色的使连续数量+1. 用掉了以后剩余部分的连续长度就是0.也许 j-1 和 j 同色,但这个可以在另一个转移里体现,所以没问题. #include<iostream> #i…
题目:https://www.luogu.org/problemnew/show/UVA10559 区间DP,有点难想: 为了方便,先把原来就是连续一段相同颜色的点看做一个点,记一下长度: f[i][j][k] 表示右边有 k 个和 j 颜色相同的点时(其它都已经各自被消掉),消除 i ~ j 区间的答案: 从消除 j 点来考虑,有两种方法:1.和右边那 k 个点合并消除,所以 f[i][j][k] = f[i][j-1][0] + ( len[j] + k )2 2.和右边以及区间中的某个相同…
题目大意:依照顺时针或者逆时针的顺序给出多边的点,要将这个多边形分解成n-2个三角形,要求使得这些三角行中面积最大的三角形面积尽量小,求最小值. 思路:用区间DP能够非常方便解决,多边形可能是凹边形,注意剖分的三角形必须在多边形内部,所以能够去掉剖分的三角形中包括其它点,可是其它的在多边形外部的三角形没想到其它方法去除.却ac了,不懂为何 // Accepted C++ 0.042 #include<cstdio> #include<iostream> #include<al…