• 【b703】矩阵取数游戏


    Time Limit: 1 second
    Memory Limit: 50 MB

    【问题描述】

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

    【输入】

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

    【输出】

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

    【输入样例1】

    2 3
    1 2 3
    3 4 2
    

    【输出样例1】

    82
    

    【输入输出样例1解释】

    第1次:第一行取行首元素,第二行取行尾元素,本次的氛围1*21+2*21=6
    第2次:两行均取行首元素,本次得分为2*22+3*22=20
    第3次:得分为3*23+4*23=56。总得分为6+20+56=82
    

    【输入样例2】

    1 4
    4 5 0 5
    

    【输出样例2】

    122
    

    【输入样例3】

    2 10
    96 56 54 46 86 12 23 88 80 43
    16 95 18 29 30 53 88 83 64 67
    

    【输出样例3】

    316994
    

    【 限制】

    60%的数据满足:1<=n, m<=30,答案不超过1016
    100%的数据满足:1<=n, m<=80,0<=aij<=1000
    

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=b703

    【题意】

    中文题

    【题解】

    这道题可以分成n个步骤;
    即每一行与每一行之间是独立的;
    所以我们可以一行一行地进行处理;

    f[i][j]表示取当前行区间[i..j]内的数能够获得的最大值;

    f[i][j] = 2*max(a[i]+f[i+1][j],f[i][j-1]+a[j]);
    这里的2对外层的区间乘的次数比较少,对内层的区间里的数乘得比较多;
    且从内到外是递增1的;
    正符合题目的要求;
    写一个记忆化搜索就好了;
    因为数据比较大;
    要写一个高精度;
    。。。
    挺麻烦的。
    (一开始那个a数组没有init调了很久。。做高精度加法的时候要注意啊,不然之前的数据会保留下来的。。)

    【完整代码】

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int MAXM = 110;
    
    struct bignum
    {
        int a[110],len;
        void init()
        {
            rep1(i,1,100)
                a[i] = 0;
        }
    };
    
    int n,m;
    bignum f[MAXM][MAXM],emp,a[MAXM],ans;
    
    bignum plu(bignum a,bignum b)
    {
        bignum c;
        rep1(i,1,100)
            c.a[i] = 0;
        c.len = max(a.len,b.len);
        int x = 0;
        rep1(i,1,c.len)
        {
            c.a[i] = c.a[i] + a.a[i]+b.a[i] + x;
            x = c.a[i]/10;
            c.a[i] %= 10;
        }
        while (x>0)
        {
            c.a[++c.len] = x;
            x = c.a[c.len]/10;
            c.a[c.len]%=10;
        }
        return c;
    }
    
    bignum ma(bignum a,bignum b)
    {
        int len1 = a.len,len2 = b.len;
        if (len1>len2)
            return a;
        else
            if (len1<len2)
                return b;
        rep2(i,len1,1)
            if (a.a[i]!=b.a[i])
            {
                if (a.a[i]>b.a[i])
                    return a;
                else
                    return b;
            }
        return a;
    }
    
    bignum dfs(int l,int r)
    {
        if (l>r) return emp;
        if (f[l][r].a[1]!=-1)
            return f[l][r];
        if (l==r)
            return plu(a[l],a[l]);
        //f[l][r] = 2*max(a[l]+dfs(l+1,r),dfs(l,r-1)+a[r]);
        bignum temp1 = plu(a[l],dfs(l+1,r));
        bignum temp2 = plu(dfs(l,r-1),a[r]);
        bignum temp3 = ma(temp1,temp2);
        return f[l][r] = plu(temp3,temp3);
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        ans.len = 1;ans.a[1] =0;ans.init();
        emp.a[1] = 0,emp.len = 1;
        emp.init();
        rei(n);rei(m);
        rep1(i,1,n)
        {
            rep1(ii,1,m)
                rep1(jj,1,m)
                {
                    f[ii][jj].init();
                    f[ii][jj].len = 1;
                    f[ii][jj].a[1] = -1;
                }
            rep1(j,1,m)
            {
                int temp,len=0;
                rei(temp);
                a[j].init();
                while (temp>0)
                {
                    a[j].a[++len] = temp%10;
                    temp/=10;
                }
                if (len==0)
                {
                    a[j].a[1] = 0;
                    a[j].len = 1;
                }
                else
                    a[j].len = len;
            }
            ans=plu(ans,dfs(1,m));
        }
        rep2(i,ans.len,1)
            printf("%d",ans.a[i]);
        return 0;
    }
    
    
  • 相关阅读:
    [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(二)
    PHP中PDO的配置与说明
    PHP输出表格的方法
    打印网格版本9*9乘法表
    js中日历的代码
    js中初学函数的使用
    c#中的23种设计模式
    用多态来实现U盘,Mp3,移动硬盘和电脑的对接,读取写入数据。
    用面向对象多态的思想分别去求圆形和长方形的面积和周长
    面向对象之多态(抽象类)
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626635.html
Copyright © 2020-2023  润新知