题目:
【问题描述】
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均
为非负整数。游戏规则如下:
1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,
其中i 表示第i 次取数(从1 开始编号);
4. 游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
分析:
很恶心,主要用dp来解题,但是dp其实很短长的是高精度- -,状态转移方程: f[i,j,k]:=max(ggj(f[i,j,k-1],mul(a[i,k],m-k+j)),ggj(f[i,j+1,k],mul(a[i,j],m-k+j)));
代码:
const
maxn=100;
var
a:array [0..maxn,0..maxn] of ansistring;
f:array [0..maxn,0..maxn,0..maxn] of ansistring;
n,m,num:longint;
ans:ansistring;
procedure init;
var
i,j:longint;
begin
readln(n,m);
for i:=1 to n do
for j:=1 to m do
begin
read(num);
str(num,a[i,j]);
end;
end;
function mul(s1:ansistring;temp:longint):ansistring;
var
c:array [1..maxn*maxn*maxn] of int64;
i,j,k:longint;
st:ansistring;
begin
k:=length(s1);
fillchar(c,sizeof(c),0);
for i:=1 to k do
c[k+1-i]:=ord(s1[i])-ord('0');
for i:=1 to k do
for j:=1 to temp do
c[i]:=c[i]*2;
for i:=1 to k do
begin
c[i+1]:=c[i+1]+c[i] div 10;
c[i]:=c[i] mod 10;
end;
if c[k+1]>0 then
inc(k);
while c[k]>=10 do
begin
c[k+1]:=c[k] div 10;
c[k]:=c[k] mod 10;
inc(k);
end;
for i:=1 to k do
st:=chr(ord('0')+c[i])+st;
mul:=st;
end;
function ggj(s1,s2:ansistring):ansistring;
var
b,c:array [0..maxn*maxn*maxn] of int64;
i,len1,len2:longint;
st:ansistring;
begin
fillchar(b,sizeof(b),0);
fillchar(c,sizeof(c),0);
len1:=length(s1);
len2:=length(s2);
for i:=1 to len1 do
b[len1-i+1]:=ord(s1[i])-ord('0');
for i:=1 to len2 do
c[len2-i+1]:=ord(s2[i])-ord('0');
if len1>len2 then
begin
for i:=1 to len1 do
c[i]:=c[i]+b[i];
for i:=1 to len1 do
begin
c[i+1]:=c[i+1]+c[i]div 10;
c[i]:=c[i]mod 10;
end;
if c[len1+1]>0 then
inc(len1);
for i:=1 to len1 do
st:=chr(c[i]+ord('0'))+st;
end
else
begin
for i:=1 to len2 do
c[i]:=c[i]+b[i];
for i:=1 to len2 do
begin
c[i+1]:=c[i+1]+c[i]div 10;
c[i]:=c[i]mod 10;
end;
if c[len2+1]>0 then
inc(len2);
for i:=1 to len2 do
st:=chr(c[i]+ord('0'))+st;
end;
ggj:=st;
end;
function max(s1,s2:ansistring):ansistring;
begin
if length(s1)>length(s2) then
exit(s1)
else
if length(s2)>length(s1) then
exit(s2)
else
if s1>s2 then
exit(s1)
else
exit(s2);
end;
procedure main;
var
i,j,k:longint;
begin
for i:=1 to n do
for j:=m downto 1 do
for k:=j to m do
f[i,j,k]:=max(ggj(f[i,j,k-1],mul(a[i,k],m-k+j)),ggj(f[i,j+1,k],mul(a[i,j],m-k+j)));
for i:=1 to n do
ans:=ggj(ans,f[i,1,m]);
writeln(ans);
end;
begin
init;
main;
end.