几个dp的小总结

将马按照顺序放在马棚中,后面的马放的马棚的序号不会大于前面的马放的马棚的序号。而且,他不想他的K个马棚中任何一个空置,也不想任何一匹马在外面。已知共有黑、白两种马,而且它们相处得并不十分融洽。如果有i个白马和j个黑马在一个马棚中,那么这个马棚的不愉快系数将是i*j。所有k个马棚不愉快系数的和就是系数总和。确定一种方法把n匹马放入k个马棚,使得系数总和最小。


设F[i][j]第i匹马放j棚,方程很简单。
--------------------------------------------


乌龟棋中M 张爬行卡片,分成4 种不同的类型(M 张卡片中不一定包含所有4 种类型的卡片,见样例),每种类型的卡片上分别标有1、2、3、4 四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到
该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。
很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。
现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
【数据范围】
对于30%的数据有1 ≤ N≤ 30,1 ≤M≤ 12。
对于50%的数据有1 ≤ N≤ 120,1 ≤M≤ 50,且4 种爬行卡片,每种卡片的张数不会超过20。
对于100%的数据有1 ≤ N≤ 350,1 ≤M≤ 120,且4 种爬行卡片,每种卡片的张数不会超过40;0 ≤ ai ≤ 100,1 ≤ i ≤ N;1 ≤ bi ≤ 4,1 ≤ i ≤M。输入数据保证N&#8722;;1=Σb_i (1<=i<=M)
输入格式
输入文件的每行中两个数之间用一个空格隔开。
第1 行2 个正整数N 和M,分别表示棋盘格子数和爬行卡片数。
第2 行N 个非负整数,a1, a2, ……, aN,其中ai 表示棋盘第i 个格子上的分数。
第3 行M 个整数,b1,b2, ……, bM,表示M 张爬行卡片上的数字。
输入数据保证到达终点时刚好用光M 张爬行卡片,即N&#8722;;1=Σb_i (1<=i<=M)
输出格式
输出只有1 行,1 个整数,表示小明最多能得到的分数。


状态设F[i][x][y][z][l]代表第i个格子共用了1卡x张,2卡y张,3.。。。。。4.。。。
方程简单就不列了。
f[350][40][40][40]
--------------------------------------------
windy有 N 条木板需要被粉刷。
每条木板被分为 M 个格子。
每个格子要被刷成红色或蓝色。
windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色。
每个格子最多只能被粉刷一次。
如果windy只能粉刷 T 次,他最多能正确粉刷多少格子?
一个格子如果未被粉刷或者被粉刷错颜色,就算错误粉刷。
solu1
设F[i][j][t][1]
    0
代表前i个木板,前j个格子,刷了t次,第t次刷的颜色
f[i][j][t][a]=f[i][k][t-1][1,0]+correct(i,k,j,a);{k<j;j>1}
f[i][1][t][a]=f[i-1][n][t-1][1,0]+correct(i,1,1,a);

solu2


设F[k][i][j][1,2]前k个木板,刷i次,刷到j格,1代表刷对这个格子,2刷错这个格子
if j=1  then begin
                    f[k,i,j,1]:=max(f[k-1,i-1,m,1],f[k-1,i-1,m,2])+1;
                    f[k,i,j,2]:=max(f[k-1,i-1,m,1],f[k-1,i-1,m,2]);
                end else
                    if col[k][j]<>col[k][j-1] then begin
                         f[k,i,j,1]:=max(f[k,i-1,j-1,1],f[k,i,j-1,2])+1;
                         f[k,i,j,2]:=max(f[k,i,j-1,1],f[k,i-1,j-1,2]);
                    end else begin
                         f[k,i,j,1]:=max(f[k,i,j-1,1],f[k,i-1,j-1,2])+1;
                         f[k,i,j,2]:=max(f[k,i-1,j-1,1],f[k,i,j-1,2]);
                    end;
                end;
end;


--------------------------------------
这次RC总共买了N种菠萝包,每种一个。每个菠萝包都有一个初始美味值Ti,每过一天就会减少Di,即第2天美味值为Ti-Di,第3天为Ti-2*Di,依此类推。一旦美味值减为负数,那个包就坏掉了,不能吃了。
RC每天都要为夏娜安排当天吃菠萝包的组合,这些组合不是随意的,而是只能从夏娜喜欢的M种搭配中挑选一种。每种搭配是由Ki个菠萝包组成的,一种搭配的总美味值是这Ki个菠萝包当天的美味值之和再加上一个额外的搭配美味值Ei。不过要注意,一旦某种搭配的其中一个菠萝包坏掉了,这个搭配就不能选用了。而且,有可能存在两个搭配,里面的组合是一样的,但额外的搭配美味值却不同。
RC想让可爱的夏娜尽可能地吃得美味,因此希望能找出一种最优的方案,让小夏娜吃上若干天的菠萝包,这些天的美味值之和最大。




设F[i][S]前i天,吃过面包集合为S(假如第u种面包吃过,S的第u二进制位为1)


F[i][S]=F[i-1][S-{j}]+value




---------------------------------------
这段路可以用一个长度为n的序列A[i]来表示,A[i]表示了第i这段路的高度。毕竟教主即使会使用魔法他还是个人,教主如果想穿越这条路线,他必须从第1段路开始走,走到第n段,从第i段走到第i+1段路需要消耗|A[i+1]-A[i]|点体力。为了节省体力,教主使出了他另一种神奇的魔法。教主的魔法可以交换相邻两段路的高度,并且这种魔法不需要花费额外的体力。但是第二次使用魔法开始,交换的两段路在路线中的位置需位于之前交换的两段路之后。即如果某次交换了A[j]和A[j+1],那么下次交换A[k]和A[k+1]必须满足j<k。 
  接着,LHX教主想规划下如何调整路段高度后穿越,使得体力消耗最小。


定义状态f[i][1]从第i个位置走到第n个位置,第i个位置换了的最优值。
f[i][0]没换最优值


F[i][0]=Min{F[i+1][0]+dis(i,i+1),F[i+1][1]+dis(i,i+2)//因为不论第i+1换到了哪,第i个总和第i+2个接触}
F[i][1]=Min{//假设将第i个换到j后面,那么从第i+1个到j的高度是不变的,还是连续整体,可以用前缀和搞定,设Si是1~i差的总和,k=Sj-Si+1,然后接上F[ j + 1]的转移即可。


F[i][1],


F[j+1][0]+abs(a[j+1]-a[i])+k+abs(a[j]-a[i]),


F[j+1][1]+abs(a[j+2]-a[i])+k+abs(a[j]-a[i])


}


-------------------------------------
LHX教主要来X市指导OI学习工作了。为了迎接教主,在一条道路旁,一群Orz教主er穿着文化衫站在道路两旁迎接教主,每件文化衫上都印着大字。一旁的Orzer依次摆出“欢迎欢迎欢迎欢迎……”的大字,但是领队突然发现,另一旁穿着“教”和“主”字文化衫的Orzer却不太和谐。
  为了简单描述这个不和谐的队列,我们用“j”替代“教”,“z”替代“主”。而一个“j”与“z”组成的序列则可以描述当前的队列。为了让教主看得尽量舒服,你必须调整队列,使得“jz”子串尽量多。每次调整你可以交换任意位置上的两个人,也就是序列中任意位置上的两个字母。而因为教主马上就来了,时间仅够最多作K次调整(当然可以调整不满K次),所以这个问题交给了你。


f[i][j][z][0]前i位,j换了j次,z换了z次,第i位是否换(1:换0:不换)
           1 


if Ai=Aj='j'
f[i][j][z][1]=max(f[i-1][j-1][z][2]+1,f[i-1][j-1][z][1]);
其他类似


---------------------------------------
 LHX教主很能跳,因为Orz他的人太多了。教主跳需要消耗能量,每跳1米就会消耗1点能量,如果教主有很多能量就能跳很高。
  教主为了收集能量,来到了一个神秘的地方,这个地方凡人是进不来的。在这里,教主的正上方每100米处就有一个能量球(也就是这些能量球位于海拔100,200,300……米处),每个能量球所能提供的能量是不同的,一共有N个能量球(也就是最后一个能量球在N×100米处)。教主为了想收集能量,想跳着吃完所有的能量球。教主可以自由控制他每次跳的高度,接着他跳起把这个高度以下的能量球都吃了,他便能获得能量球内的能量,接着吃到的能量球消失。教主不会轻功,教主不会二段跳,所以教主不能因新吃到的能量而变化此次跳跃的高度。并且教主还是生活在地球上的,所以教主每次跳完都会掉下来。
  问教主若要吃完所有的能量球,最多还能保留多少能量。


设F[i][j]跳i次,跳到第j个
F[i][j]=F[i-1][k]+value(k,i)+cost(i);{min}
设F[i-1][k]+v(k,i)+cost(i)>F[i-1][l]+v(l,i)+cost(i){l<k<i}
f[i-1][k]-f[i-1][l]>v(l,i)-v(k,i)
  >v(l,k)
式子不关于i,单调队列解决


---------------------------------------
教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值。
  教主最喜欢3种树,这3种树的高度分别为10,20,30。教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高。


比较明显的DP模型,只不过虽然是环状的,但是每个点的状态跟确定的区间长度无关,所以只需要枚举第1棵树的高度(特别注意当高度为20时要分下一棵树是10还是30),链状DP即可。
f[i][1..4]表示分别前i棵树,第i棵树的高度为10(下棵树肯定要比它高),20(下棵树比它高),20(下棵树比它矮),30(下棵树肯定要比它矮)的最大价值。转移也显而易见了。

---------------------------------------


  胖子很有钱。他购买了一个先进的跑步机(真的不一样哦~~~~)。
  这个跑步机是这样的:
  1. 可以把它看成一个N*M的矩阵。有的格子是障碍不能经过(用x表示),有的格子是空地可以经过(用.表示)。
  2. 对于每一个时段,跑步机有不同的倾斜方向。由于胖子太胖了,所以他这个时候只有2种选择:要么沿这个方向移动(每秒移动1个格子),或者艰难的保持在原来的位置不动。
  现在胖子已经设定好了跑步机在不同时段中的倾斜方向。众所周知,保持在原地不动是不会做功的。胖子要减肥就要做功。所以他想知道他最多能够跑多长的路程。

Input

  第一行5个正整数N,M,X,Y,K。 X,Y是胖子的初始位置,数据保证这个点不是障碍。
  接下来N行,每行M个字符,表示跑步机上的地形。
  最后K行,每行3个正整数S,T,W。S表示这个时段的开始时间,T(T<=10000)表示这个时段的结束时间。W表示该时段的倾斜方向。(1:上 2:下 3:左 4:右)


F[i][x][y]指在时段i,(x,y)点的最大做功。

明显F[i][x][y]=max(F[i][x][y],F[i][x][k]+Abs(y-k))//举例:当倾斜向左右上时,行号不变,列号 y-k>Ti-Si+1.

设    F[i][x][j]+y-j>F[i][x][k]+y-k

F[i][x][j]-F[i][x][k]>j-k

于是可以用这个不等式建单调队列优化Dp


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值