您的位置:首页 > 其它

【GDOI2017第二轮模拟day2】开房间

2017-04-16 22:36 375 查看
Description

A君与B君正在玩一款闯关游戏,游戏共有n关,每一关的目标只有一个:开房间。

每一关都会有m个房间(从1~m进行编号),A君与B君每关各打开一个房间即可过关,但两人不能打开同一个房间。

通过每一关后,m个房间会重新关上,在第i关打开第j个房间需要消耗t[i][j]的体力值。并且无论A君还是B君,除了第一关外,若上一关自己开了a号房间,这一关开了b号房间,则需要额外消耗K*|a-b|点体力值。

现在请你回答,两人过完全部n关后,所要消耗的体力值之和(两人消耗体力相加)最小能是多少。

Input

第一行三个整数n,m,K.

接下来n行每行m个整数,第i行第j个整数t[i][j]表示第i关开第j个房间需要消耗的体力值。

Output

仅一行一个整数表示答案。

Sample Input

3 3 10

2 13 4

4 3 2

16 4 3

Sample Output

28

Data Constraint

30%的数据:n,m <= 5

60%的数据:n,m <= 50

100%的数据:1 <= n,m <= 300 , 1 <= K,t[i][j] <= 10^6

题解

一开始比赛的时候想到用堆把一个n优化成log,但是后来发现是道套路题

我们考虑f[z,i,j]的贡献,容易发现是左上,右上,左下,右下四个方向的f[z-1,x,y]+k*曼哈顿距离+a[z,i]+a[z,j],最后两项可以最后再加上去,而前面的两项可以发现是一个二维的前缀和,所以我们可以从四个方向预处理前缀和,然后就可以O(1)算出当前位置的答案了

但是这样还是会超时,然后我们发现两个人的路径不会出现交叉的情况,那么我们强制i小于j,然后就可以把常数缩小一半,可以通过此题~

贴代码

var
f:array[0..305,0..305,0..305]of longint;
a,p1,p2,p3,p4:array[0..305,0..305]of longint;
i,j,k,l,n,m,x,y,z,ans:longint;
function min(x,y:longint):longint;inline;
begin
if x<y then exit(x) else exit(y);
end;
begin
assign(input,'room.in'); reset(input);
assign(output,'room.out'); rewrite(output);
readln(n,m,k);
for i:=1 to n do
begin
for j:=1 to m do read(a[i,j]);
readln;
end;
fillchar(f,sizeof(f),$7f);
for i:=1 to m do
for j:=1 to m do
if i<>j then f[1,i,j]:=a[1,i]+a[1,j];
fillchar(p1,sizeof(p1),$7f);
p2:=p1; p3:=p1; p4:=p1;
for z:=2 to n do
begin
for i:=1 to m-1 do
for j:=i+1 to m do
begin
if p1[i,j-1]<p1[i-1,j] then p1[i,j]:=p1[i,j-1]+k else p1[i,j]:=p1[i-1,j]+k;
if f[z-1,i,j]<p1[i,j] then p1[i,j]:=f[z-1,i,j];
end;
for i:=m-1 downto 1 do
for j:=i+1 to m do
begin
p2[i,j]:=f[z-1,i,j];
p2[i,j]:=min(p2[i,j],k+min(p2[i+1,j],p2[i,j-1]));
end;
for i:=1 to m-1 do
for j:=m downto i+1 do
begin
p3[i,j]:=f[z-1,i,j];
p3[i,j]:=min(p3[i,j],k+min(p3[i-1,j],p3[i,j+1]));
end;
for i:=m-1 downto 1 do
for j:=m downto i+1 do
begin
p4[i,j]:=f[z-1,i,j];
p4[i,j]:=min(p4[i,j],k+min(p4[i+1,j],p4[i,j+1]));
end;
for i:=1 to m-1 do
for j:=i+1 to m do
begin
//f[z,i,j]:=min(p1[i,j],min(p2[i,j],min(p3[i,j],p4[i,j])));
f[z,i,j]:=p4[i,j];
if p1[i,j]<f[z,i,j] then f[z,i,j]:=p1[i,j];
if p2[i,j]<f[z,i,j] then f[z,i,j]:=p2[i,j];
if p3[i,j]<f[z,i,j] then f[z,i,j]:=p3[i,j];
f[z,i,j]:=f[z,i,j]+a[z,i]+a[z,j];
end;
end;
ans:=maxlongint;
for i:=1 to m do
for j:=1 to m do
if i<>j then ans:=min(ans,f[n,i,j]);
writeln(ans);
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: