zoukankan      html  css  js  c++  java
  • 动态规划:矩阵取数

    题目描述 
    Description

    【问题描述】
    帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均
    为非负整数。游戏规则如下:
    1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
    2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
    3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,
    其中i 表示第i 次取数(从1 开始编号);
    4. 游戏结束总得分为m次取数得分之和。
    帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

    输入描述 Input Description

    第1行为两个用空格隔开的整数n和m。
    第2~n+1 行为n*m矩阵,其中每行有m个用单个空格隔开的非负整数。

    输出描述 Output Description

    输出 仅包含1 行,为一个整数,即输入矩阵取数后的最大得分。

    样例输入 Sample Input

    2 3
    1 2 3
    3 4 2

    样例输出 Sample Output

    82

    数据范围及提示 
    Data Size & Hint
    样例解释
    第 1 次:第1 行取行首元素,第2 行取行尾元素,本次得分为1*21+2*21=6
    第2 次:两行均取行首元素,本次得分为2*22+3*22=20
    第3 次:得分为3*23+4*23=56。总得分为6+20+56=82
     
    【限制】
    60%的数据满足:1<=n, m<=30, 答案不超过10^16
    100%的数据满足:1<=n, m<=80, 0<=aij<=1000

    一个区间动规,但加了高精就变态多了。
    f[i,j]表示以i为起点,j为终点所得的最大得分
    f[i,j]=max(f[i+1,j]*2+init[i]
    f[i,j-1]*2+init[j]);
    答案不超过10^16,要用到高精加和乘
    f[i,j,k]表示f[i,j]的第k位数

    code:
    var n,m:longint;
    ii,i,j,k,c,v,b:longint;
    init:array[0..100]of longint;
    num1,num2:array[0..60]of longint;
    f:array[1..100,1..100,0..60]of integer;
    num:array[0..60]of integer;
    len:longint;
    function max(x,y:longint):longint;
    begin if x>y
    then exit(x)
    else exit(y);
    end;
    begin readln(n,m);
    fillchar(num,sizeof(num),0);
    for ii:=1 to n do
    begin for j:=1 to m do
    read(init[j]);
    fillchar(f,sizeof(f),0);
    for i:=1 to m do
    begin k:=init[i];
    if k=0
    then begin f[i,i,0]:=1;
    f[i,i,1]:=0;
    end
    else begin j:=0;
    while k<>0 do
    begin inc(j);
    f[i,i,j]:=k mod 10;
    k:=k div 10;
    end;
    f[i,i,0]:=j;
    end;
    end;
                    for i:=1 to m-1 do
                        for j:=1 to m-i do
                            begin fillchar(num1,sizeof(num1),0);
    fillchar(num2,sizeof(num2),0);
    for c:=0 to max(f[j+1,j+i,0],f[j,j+i-1,0]) do
    begin num1[c]:=f[j,j+i-1,c];
    num2[c]:=f[j+1,j+i,c];
    end;
    for c:=1 to max(num1[0],num2[0]) do
    begin num1[c]:=num1[c]*2;
    num2[c]:=num2[c]*2;
    end;
    for c:=1 to max(num1[0],num2[0])+1 do
    begin num1[c+1]:=num1[c+1]+num1[c] div 10;
    num1[c]:=num1[c] mod 10;
    num2[c+1]:=num2[c+1]+num2[c] div 10;
    num2[c]:=num2[c] mod 10;
    end;
    c:=num1[0]+1;
    while (num1[c]=0)and(c>1) do dec(c);
    num1[0]:=c;
    c:=num2[0]+1;
    while (num2[c]=0)and(c>1) do dec(c);
    num2[0]:=c;
                                  for c:=1 to max(num1[0],f[j+i,j+i,0]) do
    begin num1[c+1]:=num1[c+1]+(num1[c]+f[j+i,j+i,c]) div 10;
    num1[c]:=(num1[c]+f[j+i,j+i,c]) mod 10;
    end;
    len:=max(num1[0],f[j+i,j+i,0])+1;
    while num1[len]=0 do dec(len);
    num1[0]:=len;
    for c:=1 to max(num2[0],f[j,j,0]) do
    begin num2[c+1]:=num2[c+1]+(num2[c]+f[j,j,c]) div 10;
    num2[c]:=(num2[c]+f[j,j,c]) mod 10;
    end;
    len:=max(num2[0],f[j,j,0])+1;
    while num2[len]=0 do dec(len);
    num2[0]:=len;
    if num1[0]>num2[0]
    then begin for c:=0 to num1[0] do
    f[j,j+i,c]:=num1[c];
    end;
    if num2[0]>num1[0]
    then begin for c:=0 to num2[0] do
    f[j,j+i,c]:=num2[c];
    end;
    if num1[0]=num2[0]
    then begin c:=num1[0];
    while (c>=1)and(num1[c]=num2[c]) do
    dec(c);
    if num1[c]=num2[c]
    then begin for v:=0 to num1[0] do
    f[j,j+i,v]:=num1[v];
    end;
    if num1[c]<num2[c]
    then begin for v:=0 to num2[0] do
    f[j,i+j,v]:=num2[v];
    end;
    if num1[c]>num2[c]
    then begin for v:=0 to num1[0] do
    f[j,i+j,v]:=num1[v];
    end;
    end;
    end;
    for i:=1 to f[1,m,0] do
    f[1,m,i]:=f[1,m,i]*2;
    for i:=1 to f[1,m,0] do
    begin f[1,m,i+1]:=f[1,m,i+1]+f[1,m,i] div 10;
    f[1,m,i]:=f[1,m,i] mod 10;
    end;
    len:=f[1,m,0]+2;
    while (f[1,m,len]=0)and(len>1) do
    dec(len);
    f[1,m,0]:=len;
    len:=max(num[0],f[1,m,0]);
    for i:=1 to len do
    begin num[i+1]:=num[i+1]+(f[1,m,i]+num[i]) div 10;
    num[i]:=(num[i]+f[1,m,i]) mod 10;
    end;
    len:=len+1;
    while (num[len]=0)and(len>1) do dec(len);
    num[0]:=len;
    end;
    for i:=num[0] downto 1 do
    write(num[i]);
    end.
  • 相关阅读:
    socketserver模块
    socketserver密文测试
    Less11-Less12
    Less-5-03
    google语法
    Nmap
    01真的很简单
    kali linux 安装后的必要修改
    SQLMap-02
    SQLMap-01
  • 原文地址:https://www.cnblogs.com/spiderKK/p/4899754.html
Copyright © 2011-2022 走看看