NOIP2007提高组 矩阵取数

13 篇文章 0 订阅
2 篇文章 0 订阅
NOIP2007提高组 矩阵取数
题目描述
    帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:
    1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
    2.每次取走的各个元素只能是该元素所在行的行首或行尾;
    3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);
    4.游戏结束总得分为m次取数得分之和。
    帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
输入输出格式
    输入格式:
    包括n+1行:
    第1行为两个用空格隔开的整数n和m。
    第2~n+1行为n*m矩阵,其中每行有m个用单个空格隔开的非负整数。
    数据范围:
    60%的数据满足:1<=n, m<=30,答案不超过10^16
    100%的数据满足:1<=n, m<=80,0<=aij<=1000
输出格式:
    仅包含1行,为一个整数,即输入矩阵取数后的最大得分。


输入输出样例
    输入样例:
    2 3
    1 2 3
    3 4 2
    输出样例:
    82
分析:
    求每一行的最大值,然后将它们的结果相加。
    对于第n行,用动态规划的方法:
    状态:f(i, j),表示在第i个元素和第j个元素之间操作是的最大值。
    初始值:当i==j时,此时只剩些一个元素,因此应该是第m次去,因此f(i, i)= matrix[n][i]*2^m;
    状态转移方程:对f(i,j),假设k=j-i+1能到达这种状态,说明已经到了m-k次取数,另一方面,可以从左取数,也可以从右取数,这两种方法的结果较大者即为f(i, j)的值。因此,f(i, j)=max(f(i+1, j) + matrix[n][i]*2^(m-k), f(i, j-1) + matrix[n][j]*2^(m-k)。

    由于数值会很大,因此必须用高精度计算(对java或c11则很好处理)。

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
         
           using namespace std; #define N 82 #define BASE 10000 int n, m; int matrix[N][N]; // 高精度计算 struct bigint{ int num[50]; // 50足够了,太大会超时 int len; bigint(): len(0){ for(int i=0; i<50; i++) num[i] = 0; } bigint operator +(bigint b); bigint operator *(bigint b); bigint operator *(int a); bigint operator = (bigint b){ len = b.len; for(int i=0; i 
          
            b.len) return 0; else{ for(int i=len-1; i>=0; i--){ if(num[i] 
           
             b.num[i]) return 0; } } return 1; } void set(int n){ if(n==0){ num[0] = 0; len = 1; } while(n){ num[len] = n % BASE; len++; n /= BASE; } } void leftmove(int k){ // 将数的右侧加k个0,在乘法中用到 int i; for(i=len; i>=0; i--) num[i+k] = num[i]; for(i=0; i 
            
              =0; i--) if(num[i]==0) len--; else break; if(len==0) len = 1; } void print(); }; bigint ans, f[N]; bigint bigint::operator +(bigint b){ int i, carry = 0, len1 = max(len, b.len); bigint tmp; for(i=0; i 
             
               0){ tmp.num[len1] = carry % BASE; carry /= BASE; len1++; } tmp.len = len1; tmp.movezero(); return tmp; } bigint bigint::operator *(int a){ int i, carry = 0, len1; bigint tmp; for(i=0; i 
              
                =0; i--){ if(i!=len-1){ if(num[i]<10) // 不足4位的补足0,以达到4位 cout<<"000"; else if(num[i]<100) cout<<"00"; else if(num[i]<1000) cout<<"0"; } cout< 
               
                 '9') ch = getchar(); while(ch<='9' && ch>='0'){ ans = ans * 10 + ch - '0'; ch = getchar(); } return ans; } bigint re[N][N]; void resolve(int n1){ int i, j, k, num ; bigint tmp1, tmp2; for(i=1; i<=m; i++) for(j=1; j<=m; j++){ re[i][j].len = 0; memset(re[i][j].num, 0, sizeof(re[i][j].num)); } // DP for(i=1; i<=m; i++) // 初始化 re[i][i] = f[m] * matrix[n1][i]; for(k=1; k 
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

2017游戏大厅大全,就在搜狗游戏大厅 2017火爆的网页游戏,就在搜狗游戏大厅点击下载游戏大厅, yxdt.sogou.com · 2018-1-27 · 搜狗广告 矩阵取数游戏 - Vijos 描述 帅帅经常同学一个矩阵取数游戏:对于一个给定的n*m的矩阵矩阵的每个元素aij据为非负整数。游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个。 https://vijos.org/p/1378 p1378 - Vijos 矩阵取数游戏 (game.pas/c/cpp) 【问题描述】 帅帅经常跟同学一个矩阵取数游戏:对于一个给定的n*m的矩阵矩阵的每个元素aij均为非负整数。游戏规则 ... https://vijos.org/discuss/5109fde44e4112501400074b 2009-9-15 错别字 - Vijos #论字打的快的后果 帅帅经常**同学**一个矩阵取数游戏:对于一个给定的n×m的矩阵矩阵的每个元素aij**据为**非负整数。 同学->跟同学 据为非负 ... https://vijos.org/discuss/57c2840f17f3ca4a05f6a0ad 2016-8-28 我知道估计没人解答,我自己看了都长的程序 - Vijos 矩阵取数游戏 登录后创建讨论 查看题目 登录后递交 讨论 题解 信息 ID 1378 难度 6 分类 动态规划 | 高精度 点击显示 标签 NOIP 2007 提高 递交数 4072 已通过 956 23% ... https://vijos.org/discuss/5109fddf4e411250140003d0 2009-7-12 难得过了,简单的栽了。请指点! - Vijos / Vijos / 讨论 / 矩阵取数游戏 / 难得过了,简单的栽了。请指点! 矩阵取数游戏 Lemon tree LV 8 @ 2009-07-27 18:34:33 编译通过... ├ 测试数据 01 ... https://vijos.org/discuss/5109fde04e4112501400049d 2009-7-27 讨论 - Vijos
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值