题目描述 Description
出于某些方面的需求,我们要把一块N×M的木板切成一个个1×1的小方块。
对于一块木板,我们只能从某条横线或者某条竖线(要在方格线上),而且这木板是不均匀的,从不同的线切割下去要花不同的代价。而且,对于一块木板,切割一次以后就被分割成两块,而且不能把这两块木板拼在一起然后一刀切成四块,只能两块分别再进行一次切割。
现在,给出从不同的线切割所要花的代价,求把整块木板分割成1×1块小方块所需要耗费的最小代价。
输入描述 Input Description
输入文件第一行包括N和M,表示长N宽M的矩阵。
第二行包括N-1个非负整数,分别表示沿着N-1条横线切割的代价。
第二行包括M-1个非负整数,分别表示沿着M-1条竖线切割的代价。
输出描述 Output Description
输出一个整数,表示最小代价。
样例输入 Sample Input
2 2
3
3
样例输出 Sample Output
9
数据范围及提示 Data Size & Hint
对于60%的数据,有1≤N,M≤100;
对于100%的数据,有1≤N,M≤2000。
分析:每一个分割线都要切,对于同一行或同一列,一定是先切大的代价,再切小的(后面的一定要多割)。然后dp行和列,看每次要割行还是列即可。
代码:
const
maxn=2000;
type
arr=array [0..maxn] of longint;
var
f:array [0..maxn,0..maxn] of longint;
hang,lie:arr;
n,m,i,j,s:longint;
procedure qsort(l,r:longint;var a:arr);
var
i,j,key,temp:longint;
begin
if l>=r then exit;
i:=l;j:=r;
key:=a[l+random(r-l+1)];
repeat
while (a[i]>key) do inc(i);
while (a[j]<key) do dec(j);
if i<=j then
begin
temp:=a[i];a[i]:=a[j];a[j]:=temp;
inc(i);dec(j);
end;
until i>j;
qsort(l,j,a);
qsort(i,r,a);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
begin
readln(n,m);
n:=n-1; m:=m-1;
for i:=1 to n do
read(hang[i]);
for i:=1 to m do
read(lie[i]);
qsort(1,n,hang);
qsort(1,m,lie);
for i:=1 to m do
begin
s:=s+lie[i];
f[i,0]:=s;
end;
s:=0;
for i:=1 to n do
begin
s:=s+hang[i];
f[0,i]:=s;
end;
for i:=1 to m do
for j:=1 to n do
f[i,j]:=min(f[i-1,j]+lie[i]*(j+1),f[i,j-1]+hang[j]*(i+1));
writeln(f[m,n]);
end.