Tvyj1061
Mobile Service
一个公司有三个移动服务员。如果某个地方有一个请求,某个员工必须赶到那个地方去(那个地方没有其他员工),某一时刻只有一个员工能移动。被请求后,他才能移动,不允许在同样的位置出现两个员工。从p到q移动一个员工,需要花费c(p,q)。这个函数没有必要对称,但是c(p,p)=0。公司必须满足所有的请求。目标是最小化公司花费。
第一行有两个整数L,N(3<=L<=200, 1<=N<=1000)。L是位置数;N是请求数。每个位置从1到L编号。下L行每行包含L个非负整数。第i+1行的第j个数表示c(i,j) ,并且它小于2000。最后一行包含N个数,是请求列表。一开始三个服务员分别在位置1,2,3。
Sample In
5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0
4 2 4 1 5 4 3 2 1
Sample Out
5
这题目有三个状态x1,x2,x3分别是三个人的位置
易得当前把X1赶去p[j]的转移
f[i,p[i],x2,x3]:=f[i,x1,x2,x3]+map[x1,p[i]]
同理
f[i,x1,p[i],x3]:=f[i,x1,x2,x3]+map[x2,p[i]]
f[i,x1,x2,p[i]]:=f[i,x1,x2,x3]+map[x3,p[i]]
但是这里有一个冗余的状态,就是{上一次的位置一定是这一次某个人的位置}
所以简化方程得
f[i,x2,p[i-1]]:=f[i-1,x1,x2]+map[x1,p[i]];
f[i,x1,p[i-1]]:=f[i-1,x1,x2]+map[x2,p[i]];
f[i,x1,x2]:=f[i-1,x1,x2]+map[p[i-1],p[i]];
当三个人的位置是x1,x2,p[i-1]时
让x1去p[i],,这时位置变成p[i],x2,p[i-1]
我们只记录x2和p[i-1]
所以f[i,x2,p[i-1]]:=f[i-1,x1,x2]+map[x1,p[i]];
如此类推就把一个人的位置给压缩掉了(还可以滚动数组优化)
矿工配餐
http://www.tyvj.cn/Problem_Show.asp?id=1180
现有两个煤矿,每个煤矿都雇用一组矿工。采煤工作很辛苦,所以矿工们需要良好饮食。每当一辆食品车到达煤矿时,矿工们便会产出一定数量的煤。有三种类型的食品车:肉车,鱼车和面包车。
矿工们喜欢变化的食谱。如果提供的食品能够不断变化,他们的产煤量将会增加。每当一个新的食品车到达煤矿时,矿工们就会比较这种新的食品和前两次(或者少于两次,如果前面运送食品的次数不足两次)的食品,并且:
如果这几次食品车都是同一类型的食品,则矿工们产出一个单位的煤。
如果这几次食品车中有两种不同类型的食品,则矿工们产出两个单位的煤。
如果这几次食品车中有三种不同类型的食品,则矿工们产出三个单位的煤。
预先已知食品车的类型及其被配送的顺序。通过确定哪车食品送到哪个煤矿可以影响产煤量。食品车不能被拆分,每个食品车必须被全部送到一个或另一个煤矿。两个煤矿也并不要求接收相同数量的食品车(事实上,也允许将所有食品车都送到一个煤矿)。
任务
给出食品车的类型及其被配送的顺序,要求你写一个程序,确定哪个食品车应被送到煤矿1,哪个食品车应被送到煤矿2,以使得两个煤矿的产煤量的总和最大。
输入的第一行包含一个整数N (1 ≤ N ≤ 100 000), 表示食品车的数目。求最大采矿量
样例输入1
6
MBMFFB
样例输出1
12
样例输入2
16
MMBMBBBBMMMMMBMB
样例输出2
29
食物的种类只有三种[0..3,0..3,0..3,0..3]满足空间时间大小
所以记录状态f[i,a1,a2,b1,b2]代表前两次两矿的食品种类
同理有一个状态肯定是上一次食品车的种类 所以压缩一个变量得
f[i,s[i],pa1,pb1,pb2]=max{f[i-1,pa1,pa2,pb1,pb2]+w(s[i],pa1,pa2)}
f[i,pa1,pa2,s[i],pb1]=max{f[i-1,pa1,pa2,pb1,pb2]+w(s[i],pb1,pb2)}
(1<=i<=n ,0<=pa1<=3 ,0<=pa2<=3 ,0<=pb1<=3 ,0<=pb2<=3)
最后就是W(a,b,c)的函数要小心
同理可以做到滚动数组
总的来说 就是要注意有没有冗余的状态 有的话 一定要简化再简化