zoukankan      html  css  js  c++  java
  • 矩阵取数游戏 2007年NOIP全国联赛提高组(dp+高精)

    矩阵取数游戏

     

    2007年NOIP全国联赛提高组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
     
    题目描述 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, 答案不超过1016
    100%的数据满足:1<=n, m<=80, 0<=aij<=1000

    /*
    高精 恶心的我啊!
    终于大概差不懂几乎弄懂了封装怎么压位
    就是那个高精*低精调不出来,只能写高精*高精+压位
    注意输出时先输出第一个然后再setfill setw时压几位就是几 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iomanip>
    
    #define N 81
    #define ll long long
    #define mod 10000
    
    using namespace std;
    ll n,m,k,cnt,flag;
    ll a[N][N];
    
    inline ll read()
    {
        ll x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    class Big{
        
        public:
            
            int size,num[201];
            
            Big(){size=0;memset(num,0,sizeof num);}
            Big(int data)
            {
                size=0;
                while(data!=0){num[++size]=data%mod;data/=mod;}
            }
            inline void init(int data)
            {
                size=0;
                while(data!=0){num[++size]=data%mod;data/=mod;}
            }
            inline void copy(Big A)
            {
                int s1=size,s2=A.size;size=s2;
                for(int i=s2;i>=1;i--) num[i]=A.num[i];
            }
            
    };
    Big f[N][N],Pow[N];
    Big ans;
    
    ostream & operator << (ostream & os,Big A)
    {
        int s=A.size;
        if(s==0) os<<0,flag=1;
        if(!flag)
        {
            os<<A.num[s];
            for(int i=s-1;i;i--) os<<setfill('0')<<setw(4)<<A.num[i];
            return os;
        }
    }
    
    Big operator + (Big A,Big B)
    {
        Big c;
        int s=max(A.size,B.size);
        c.size=s;
        for(int i=1;i<=s;i++) c.num[i]=A.num[i]+B.num[i];
        for(int i=1;i<=s;i++)
          if(c.num[i]>=mod) 
          {
                c.num[i+1]+=c.num[i]/mod;
                c.num[i]%=mod;
          }
        if(c.num[s+1]!=0) c.size++;
        return c;
    }
    
    Big operator * (Big A,Big B)
    {
        Big c;
        int s1=A.size,s2=B.size;
        for(int i=1;i<=s1;i++)
          for(int j=1;j<=s2;j++)
            {
                c.num[i+j-1]+=A.num[i]*B.num[j];
                c.num[i+j]+=c.num[i+j-1]/mod;
                c.num[i+j-1]%=mod;
            }
        c.size=A.size+B.size;
        while(c.num[c.size]==0) c.size--;
        return c;
    }
    
    bool operator > (Big A,Big B)
    {
        int s1=A.size,s2=B.size;
        if(s1<s2) return 0;
        if(s1>s2) return 1; 
        for(int i=s1;i>=1;i--)
          if(A.num[i]<B.num[i]) return 0;
          else if(A.num[i]>B.num[i]) return 1;
        return 0;
    }
    
    Big Cmax(Big A,Big B)
    {
        if(A>B) return A;
        else return B; 
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) 
          a[i][j]=read();
        memset(Pow,0,sizeof Pow);
        Pow[1].init(2);
        for(int i=2;i<=m;i++) 
          Pow[i].copy(2*Pow[i-1]);
        for(int i=1;i<=n;i++)
        {        
            memset(f,0,sizeof f);
            for(int j=1;j<=m;j++) 
              f[j][1].copy(a[i][j]*Pow[m]);
              for(int k=2;k<=m;k++)
                for(int j=1;j<=m-k+1;j++)
                 f[j][k].copy(Cmax(f[j][k-1]+a[i][j+k-1]*Pow[m-k+1],f[j+1][k-1]+a[i][j]*Pow[m-k+1]));
                  
            ans.copy(ans+f[1][m]);
        }
        cout<<ans;
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    分布式跑批的实现流程
    Java1.8新特性Stream流处理集合元素
    RocketMQ消息存储和查询原理(引用清幽之地 清幽之地的博客)
    Markdown使用持续更新
    一次百万请求mq堆积的生产排查
    Spring Boot打包部署修改jar文件名
    Spring Boot的应用启动器
    Spring Boot配置文件application.properties
    Eclipse中出现.classPath(拒绝访问)
    PHP文件上传的相关配置
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7704012.html
Copyright © 2011-2022 走看看