• 一本通1574矩阵取数游戏


    1574:矩阵取数游戏

    时间限制: 1000 ms         内存限制: 524288 KB

    题目描述

    原题来自:NOIP 2007

    帅帅经常和同学玩一个矩阵取数游戏:对于给定的 n×m 的矩阵,矩阵中每个元素 aij 均为非负整数。游戏规则如下:

    1. 每次取数时必须从每行各取走一个元素,共 n 个,m 次取完所有元素。
    2. 每次取走的各个元素只能是该元素所在行行首或行尾。
    3. 每次取数都有一个的分值,为每行取数得分之和,每行取数得分==被取走元素值 2^i,其中 ii 表示第 i 次取数,从 1 开始计数。
    4. 游戏结束时,总得分为 m 次取数得分之和。

    帅帅想让你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

    输入格式

    输入包括  n+1 行。 第一行两个空格隔开的正整数 n,m 接下来 n 行每行 m 个用空格隔开的整数。

    输出格式

    输出为一个整数,为所输入矩阵取数后的最大得分

    样例

    样例输入 1

    2 3
    1 2 3
    3 4 2

    样例输出 1

    82

    样例解释 1

    第一次:第一行取行首元素,第二行取行尾元素,本次得分为 1*2^1+2*2^1=6
    第二次:两行均取行首元素,本次得分为 2×2^2+3×2^2=20;
    第三次:本次得分为 3×2^3+4×2^3=56,总得分为 6+20+56=826+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% 的数据,1n,m30,答案不超过 10^16;
    对于 100% 的数据,1n,m80,0ai,j1000。

    sol:区间dp,被高精恶心到了

    #include <bits/stdc++.h>
    using namespace std;
    const int N=85;
    const int L=105,Power=4,Base=10000;
    int n,m,a[N];
    struct Bignum
    {
        int a[L];
        Bignum(){memset(a,0,sizeof a);}
        Bignum(int x)
        {
            memset(a,0,sizeof a);
            while(x) {a[++*a]=x%10; x/=10;}
            return;
        }
        inline void Print()
        {
            int i;
            printf("%d",a[*a]);
            for(i=*a-1;i>=1;i--)
            {
                if(a[i]<1000) putchar('0');
                if(a[i]<100) putchar('0');
                if(a[i]<10) putchar('0');
                printf("%d",a[i]);
            }
            puts("");
            return;
        }
        inline void Init()
        {
            memset(a,0,sizeof a);
        }
    }Bin[N],dp[N][N];
    inline bool operator<(const Bignum &p,const Bignum &q)
    {
        if(p.a[0]!=q.a[0]) return (p.a[0]<q.a[0])?1:0;
        int i;
        for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i])
        {
            return (p.a[i]<q.a[i])?1:0;
        }
        return 0;
    }
    inline Bignum max(Bignum p,Bignum q)
    {
        return (p<q)?(q):(p);
    }
    inline Bignum operator+(const Bignum &p,const Bignum &q)
    {
        int i;
        Bignum ans=p;
        for(i=1;i<=q.a[0];i++)
        {
            ans.a[i]+=q.a[i];
            if(ans.a[i]>=Base){ans.a[i+1]+=ans.a[i]/Base; ans.a[i]%=Base;}
        }
        while(ans.a[ans.a[0]+1]) ans.a[0]++;
        return ans;
    }
    inline Bignum operator*(const Bignum &p,const Bignum &q)
    {
        int i,j;
        Bignum ans;
        ans.a[0]=p.a[0]+q.a[0];
        for(i=1;i<=p.a[0];i++)
        {
            for(j=1;j<=q.a[0];j++)
            {
                ans.a[i+j-1]+=p.a[i]*q.a[j];
                if(ans.a[i+j-1]>Base)
                {
                    ans.a[i+j]+=ans.a[i+j-1]/Base;
                    ans.a[i+j-1]%=Base;
                }
            }
        }
        while(!ans.a[ans.a[0]]) ans.a[0]--;
        return ans;
    }
    inline Bignum operator*(const Bignum &p,const int &q)
    {
        int i;
        Bignum ans;
        ans.a[0]=p.a[0]+5;
        for(i=1;i<=p.a[0];i++)
        {
            ans.a[i]+=p.a[i]*q;
            if(ans.a[i]>Base)
            {
                ans.a[i+1]+=ans.a[i]/Base; ans.a[i]%=Base;
            }
        }
        while(!ans.a[ans.a[0]]) ans.a[0]--;
        return ans;
    }
    inline Bignum Solve()
    {
        int i,j;
        for(i=1;i<=m;i++)
        {
            for(j=1;j+i-1<=m;j++)
            {
                int l=j,r=j+i-1;
                dp[l][r]=max(dp[l][r-1]+Bin[m-i+1]*a[r],dp[l+1][r]+Bin[m-i+1]*a[l]);
            }
        }
    //    dp[1][m].Print();
        return dp[1][m];
    }
    int main()
    {
        int i,j;
        Bignum ans;
        scanf("%d%d",&n,&m);
        Bin[0]=Bignum(1);
        for(i=1;i<=m;i++) Bin[i]=Bin[i-1]*2;
    //    for(i=1;i<=m;i++)
    //    {
    //        Bin[i].Print();
    //    }
    //    puts("");
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++) scanf("%d",&a[j]);
            ans=ans+Solve();
        }
        ans.Print();
        return 0;
    }
    View Code
  • 相关阅读:
    通过API方式查看Azure Sign-ins记录
    定期删除Azure存储账号下N天之前的数据文件-ASM
    定期删除Azure存储账号下N天之前的数据文件-ARM
    使用自定义映像批量创建托管磁盘虚拟机
    CentOS6.9 ARM虚拟机扩容系统磁盘
    Linux小技巧
    mysql数据导到本地
    mac安装pkg 一直“正在验证” 卡着
    idea compare功能 之一次bug修复
    番茄三月账单
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10354899.html
Copyright © 2020-2023  润新知