Dp专题
1011: KC的瓷器 (porcelain)
题目描述
KC来到了一个盛产瓷器的国度。他来到了一位商人的店铺。在这个店铺中,KC看到了一个有n(1<=n<=100)排的柜子,每排都有一些瓷器,每排不超过100个。那些精美的艺术品使KC一下心动了,决定从N排的商品中买下m(1<=m<=10000)个瓷器。
这个商人看KC的脸上长满了痘子,就像苔藓一样,跟精美的瓷器相比相差太多,认为这么精致的艺术品被这样的人买走艺术价值会大打折扣。商人感到不爽,于是规定每次取商品只能取其中一排的最左边或者最右边那个,想为难KC。
现在KC又获知每个瓷器的价值(用一个不超过100的正整数表示),他希望取出的m个商品的总价值最大。
输入
第一行包括两个正整数n,m;
接下来2到n+1行,第i行第一个数表示第i排柜子的商品数量Si,接下来Si个数表示从左到右每个商品的价值。
输出
只有一个正整数,即m个商品最大的总价值。
【数据范围】
对于10%的数据,Si=1,1<=i<=n。
对于另外10%的数据,n=1.
solution
令f[i][j]表示前i个柜子买j个瓷器的最大收益
预处理g[i][j]表示第i个柜子买j个瓷器的最大收益
效率O(n^3+n^2*m)
1103: 画山 paint
题目描述
有一张大小为n*m的白纸,小R想在纸上画一片绵延的群山。
为了描述方便,我们将纸张表示在坐标系上,四个顶点的坐标分别为(0,0),(n,0),(0,m),(n,m)。
小R有一只神奇的画笔,能画p种不同的线段,每种线段用两个参数a,b表示,若画笔停留的位置为(x,y),则能画一条从(x,y)到(x+a,y+b)的线段,然后画笔停留在(x+a,y+b),每种线段能画任意次。
小R需要从(0,0)开始,在(n,0)结束,在不超过纸张大小的范围内(可以在边界上)画一片绵延的群山。求一共有多少种本质不同的山形(亦即我们不认为画两次(1,1)和画一次(2,2)有任何区别)。由于结果可能会很大,你只需输出对1,000,000,007取模后的值。
输入
三个整数n,m,p分别描述纸张的大小和可画线段的总数。
接下来p行每行两个参数ai,bi描述画笔可画的第i种线段。
输出
一个整数表示本质不同的山形数对1,000,000,007取模后的值。
【数据范围】
对于40%的数据,n,m,p≤10
对于100%的数据,n,m,p≤100,1≤ai≤10,-10≤bi≤10
考虑如何防止画出形状一样的山
把相同斜率的压在一起,记这种斜率能多少步
令f[i][j][k]表示当前走到(i,j),最后一步的斜率为k
转移时枚举一个点,枚举斜率和步数,就可以得到(x',y')
那么我们把f[i][j][所有的k]加起来,记为S[i][j]
f[i][j][k]=S[x][y]-f[x][y][k];
效率O(nmp)
1149: 工具箱 ( tool )
题目描述
小明参加了机器人设计大赛。
他预设计了N种机器人,每种机器人都是由P个不同模块中选取几个组装而成。
例如有2种机器人,共11种模块,
机器人1:0 5 6 8
机器人2:3 8 9 10
表示机器人1由模块0、5、6、8组装而成。机器人2由模块3、8、9、10组装。
不会出现类似
机器人1:3 3 4 5 这样使用重复模块的情况。
为了组装出他设想的几款机器人,小明需要购买几套工具箱。到了商店,小明发现有M种工具箱(i=0~M-1),每套工具箱里包含了若干种机器模块(无重复)。
由于工具箱都是成套出售的,所以,小明只能根据设想的几款机器人所需的模块,购买若干套工具箱。为了省钱,小明希望知道,买哪些工具箱,能够分别组装出所有预想的机器人。
输入
第1行:N M P (1<=N<=100 1<=M<=100 1<=P<=16)表示有N种机器人,M套工具箱,P种模块
接下来N行P列,由0或1组成,表示第i种机器人是否需要第j种模块
再接下来M行P列,由0或1组成,表示第i套工具箱是否包含第j种模块
最后一行为M个数,分别表示第i套工具箱的价格Vi (1<=Vi<=100).
输出
输出最小费用. 如果不能达到小明的要求,输出一行"Err"(不含引号)
样例输入
<span style="color:#333333"><span style="color:#333333">2 3 2
0 1
0 1
1 1
0 1
1 1
39 36 99
</span></span>
样例输出
<span style="color:#333333"><span style="color:#333333">36
</span></span>
来源
solution
简单状压dp
f[i][S]表示前i个组成状态S的最小代价
1196: 围豆豆 bean
题目描述
是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧。
游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗豆子,每颗豆有不同的分值Vi。游戏者可以选择任意一个方格作为起始格,每次移动可以随意的走到相邻的四个格子,直到最终又回到起始格。最终游戏者的得分为所有被路径围住的豆豆的分值总和减去游戏者移动的步数。矩阵中某些格子内设有障碍物,任何时刻游戏者不能进入包含障碍物或豆子的格子。游戏者可能的最低得分为0,即什么都不做。
注意路径包围的概念,即某一颗豆在路径所形成的多边形(可能是含自交的复杂多边形)的内部。下面有两个例子:
第一个例子中,豆在路径围成的矩形内部,所以豆被围住了。第二个例子中,虽然路径经过了豆的周围的8个格子,但是路径形成的多边形内部并不包含豆,所以没有围住豆子。
布布最近迷上了这款游戏,但是怎么玩都拿不了高分。聪明的你决定写一个程序来帮助他顺利通关。
输入
第一行两个整数N和M,为矩阵的边长。
第二行一个整数D,为豆子的总个数。
第三行包含D个整数V1到VD,分别为每颗豆子的分值。
接着N行有一个N×M的字符矩阵来描述游戏矩阵状态,0表示空格,#表示障碍物。而数字1到9分别表示对应编号的豆子。
输出
仅包含一个整数,为最高可能获得的分值。
样例输入
3 8
3
30 -100 30
00000000
010203#0
00000000
样例输出
38
提示
【数据规模】
50%的数据满足1≤D≤3。
100%的数据满足1≤D≤9,1≤N, M≤10,-10000≤Vi≤10000。
来源
solution
考虑枚举起点(也是终点)
记状态f[i][j][S]表示走到(i,j),围住的豆豆的状态为S时的最大收益
显然一个状态第一次走到时最优(绕一圈不优)
现在还有一个问题:怎么判一个点有没有被包住
射线法。
对于一个点,取上端引射线
1443: 奶牛逃亡(cowrun)
题目描述
Farmer John忘记修复他农场篱笆上的一个大洞,以至于篱笆围着的N(1<= N <=1,000)只奶牛从大洞中逃脱出来,并在农场里横冲直撞。每头在篱笆外的奶牛每分钟都将给他带来一美元的损失。FJ必须遍及每头奶牛、安抚它们来停止这些损失。幸运的是,这些奶牛被定位在农场外的直线道路上的不同位置。 FJ知道每头奶牛相对于FJ的位置P_I(-500,000<= P_I的<=500000,P_I=0),FJ所处的位置记为位置0。FJ每分钟可以移动一个单位的距离,并可以当即完成对奶牛的安抚,停止他们造成的损失。请确定FJ安抚奶牛的顺序,使得他可以最大限度地减少经济损失,并计算出在此顺序下的总损失。
输入
第1行:奶牛的数目N
第2..N+1行:第I+1行包含一个整数Pi
输出
输出仅一行,输出所得到的最低总损失。
样例输入
4
-2
-12
3
7
样例输出
50
提示
安抚奶牛的顺序为:-2-->3-->7-->-12
来源
solution
可以发现安抚一定是安抚了连续的一段,因为路过而不安抚一定不优
于是令f[i][j][0/1]表示安抚了i~j 0表示停留在i 1表示停留在j
有f[i-1][j][k]=f[i][j][k]+cost();
主动转移即可
1552: 网络小说分组(novel)
YK酷爱阅读网络小说,读起来便是没日没夜废寝忘题的。
YK在机房中,花了数个月阅读完了N本网络小说,并且对N本网络小说设定了一个喜爱值,可正可负。
由于YK的U盘的容量完全被小说占据,于是她决定对小说进行分组压缩。每组小说一定是要连续的,并且每组小说的喜爱值之和必须非负。
YK想要知道方案共有多少个。
例如4本网络小说,喜爱值分别为2,3,-3,1。那么有4种方案(2 3 -3 1);(2 3 -3) (1);(2) (3 -3 1);(2) (3 -3) (1)。
100%的数据满足N≤10^5
solution
f[i]表示前i本书分组的方案数
可这会T
用权值线段树维护之前dp值,每次查询0~i 的区间和,单点修改。
1606: 平衡奶牛品种 (breeds)
题目描述
Farmer John通常使用圆形的印章来标识他的奶牛。但是最近他的印章坏掉了!因此他决定使用括号形--()印章来标识每头奶牛。在他的农场有两个品种的奶牛:Holsteins 和 Guernseys。他标识每一头奶牛使用一个括号印章。根据奶牛的朝向,可能是一个左括号或者一个右括号。
FJ的N头奶牛全部站立在一排,每头奶牛朝向任意方向,这样所有奶牛的标记看起来像一个长度为N的括号字符串。经过仔细的观察,FJ发现一个值得注意的现象:如果他从左至右(依照她们的顺序),只看Holsteins奶牛,组成一个平衡的括号字符串;对于Guernseys奶牛存在同样的事实!为了验证这是否是一个偶然现象,请帮FJ计算有多少种方法来安排他的奶牛品种,使得这种特征成立。
如何定义平衡的括号字符串,有很多种方法。一种最简单的定义是“(”的总0数目和“)”的总数目相同,对于字符串的任一前缀“(”的数目不少于“)”的数目。例如,下面的字符串都是平衡的:
()
(())
()(()())
下面的字符串是不平衡的:
)(
())(
((())))
输入
*1行:一个长度为N的括号字符串(1 <= N <= 1000)。
输出
*1行:一个单独的整数,FJ有多少种方法来安排奶牛品种,使得Holsteins奶牛组成一个平衡的括号字符串,Guernseys也组成一个平衡的括号字符串。因为答案可能会很大,请除余2012后输出(mod 2012后输出)。品种安排包括只有一个品种的情况。
提示
以下的品种安排是可行的:
(())
HHHH
(())
GGGG
(())
HGGH
(())
GHHG
(())
HGHG
(())
GHGH
solution
令f[i][x][y]表示当前做到第i位,H有x个‘(’没有匹配,G有y个‘(’没有匹配
根据当前的符号来转移,滚动一维即可
注意i-1<0可能越界
1608: 新三国争霸(fight)
题目描述
PP 特别喜欢玩即时战略类游戏,但他觉得那些游戏都有美中不足的地方。灾害总不降临道路,而只降临城市,而且道路不能被占领,没有保护粮草的真实性。于是他就研发了《新三国争霸》。
在这款游戏中,加入灾害对道路的影响(也就是一旦道路W[i,j]受到了灾害的影响,那么在一定时间内,这条路将不能通过)和道路的占领权(对于一条道路W[i,j],至少需要K[i,j]个士兵才能守住)。当灾难发生时,不能在发生灾难的道路驻扎士兵。
PP可真是高手,不一会,就攻下了N-1座城市,加上原来的就有N座城市了,但他忽略了一点……那就是防守同样重要,不过现在还来的及。因为才打完仗所以很多城市都需要建设,PP估算了一下,大概需要T天。他现在无暇分身进攻了,只好在这T天内好好的搞建设了。所以他秒要派士兵占领一些道路,以确保任何两个城市之间都有路(不然敌人就要分而攻之了,是很危险的)。士兵可不是白干活的,每个士兵每天都要吃掉V的军粮。因为有灾害,所以方案可能有变化(每改变一次就需要K的军粮,初始方案也需要K的军粮)。
因为游戏是PP编的,所以他知道什么时候有灾害。PP可是一个很节约的人,他希望这T天在道路的防守上花最少的军粮。
N<=300,M<=5000 ,T<=50;
v<=20,p<=10000,c<=300
输入
第一行有5个整数N,M,T,V,K。N表示有城市数,M表示道路数,T表示需要修养的天数,V表示每个士兵每天吃掉的军粮数,K表示修改一次花掉的军粮数。
以下M行,每行3个数A,B,C。表示A与B有一条路(路是双向的)需要C个士兵才能守住。
第M+2行是一个数P,表示有P个灾害。
以下P行,每行4个数,X,Y,T1,T2。表示X到Y的这条路,在T1到T2这几天都会受灾害。
输出
T天在道路的防守上花费最少的军粮。
来源
solution
令·f[i]表示前i天养生的最小代价
我们考虑枚举某一段时间,该段时间派兵的状态没有变化
(我本来想把派兵状态记进状态里,然后发现根本不行 枚举就行了)
f[i]=min(f[i],f[j]+(i-j)*v*get(j+i,.i)+cost);
get表示j+1~i要状态不变应该派几个兵,kruskal求解
效率O(t*t*M)
1751: 小P 的牧场(pasture)
题目描述
小P是个特么喜欢玩MC 的孩纸。。。
小P在MC 里有n 个牧场,自西向东呈一字形排列(自西向东用1...n 编号),于是他就烦恼了:为了控制这n 个牧场,他需要在某些牧场上面建立控制站,每个牧场上只能建立一个控制站,每个控制站控制的牧场是它所在的牧场一直到它西边第一个控制站的所有牧场(它西边第一个控制站所在的牧场不被控制)(如果它西边不存在控制站,那么它控制西边所有的牧场),每个牧场被控制都需要一定的花费(毕竟在控制站到牧场间修建道路是需要资源的嘛~),而且该花费等于它到控制它的控制站之间的牧场数目(不包括自身,但包括控制站所在牧场)乘上该牧场的放养量,在第i 个牧场建立控制站的花费是ai,每个牧场i 的放养量是bi,理所当然,小P需要总花费最小,但是小P的智商有点不够用了,所以这个最小总花费就由你来算出啦。
对于10%的数据,1 <= n <= 10
对于30%的数据,1 <= n <= 1000
对于100%的数据,1 <= n <= 1000000 , 0 < ai,bi <= 10000
solution
f[i]表示在i建站的花费
令sb[i]=b的前缀和,S[i]为b*sum的前缀和
带入上式
化简
b=y+kx
y递增,x递增,k递减
斜率优化,效率O(n)
2004: 象棋Chess(Chess)
题目描述
在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。
请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧
输入
一行包含两个整数N,M,中间用空格分开.
输出
输出所有的方案数,由于值比较大,输出其mod 9999973
样例输入
1 3
样例输出
7
(除了在3个格子中都放满炮的的情况外,其它的都可以.)
【约定】
100%的数据中N,M不超过100
50%的数据中,N,M至少有一个数不超过8
30%的数据中,N,M均不超过6
solution
可以发现每行和每列最多只能放两个
于是我可以枚举行,记列的状态
f[i][j][k]表示前i行 有j列放了1个,k列放了两个
主动转移更好理解,注意边界
2057: Bytecomputer
给定一个{-1,0,1}组成的序列,你可以进行x[i]=x[i]+x[i-1]这样的操作,求最少操作次数使其变成不降序列。
solution
令f[i][-1/0/1]表示当前做到iQ且使第i位为(-1,、0、1)的操作数
按a分类转移
4012: 分赃不均(kas)
仗助、亿太、胖重分赃不均闹起来了。
仗助和亿太拿着n张面值分别为a[i]的钞票决定均分,他们希望把钞票分成金额相等的两份,且未分配的剩余钞票总金额最小。
对于剩余的部分,则用替身能力复制成两倍再均分(大雾)。
求他们最终各自能带回家的金额。
solution
令f[i][S]表示前i张钱,差值为S的最大相等金额
根据第i张钞票如何分配转移
错误思路:f[i][j]表示前i张钱能否组成j
反例 2 1 2 可以组成 1 2 但不能均分