zoukankan      html  css  js  c++  java
  • 18.7.27 luogu P1005 矩阵取数游戏

    题目描述

    帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n imes mn×m 的矩阵,矩阵中的每个元素 a_{i,j}ai,j 均为非负整数。游戏规则如下:

    1. 每次取数时须从每行各取走一个元素,共 nn 个。经过 mm 次后取完矩阵内所有元素;
    2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
    3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值  imes 2^i×2i ,其中 ii 表示第 ii 次取数(从 11 开始编号);
    4. 游戏结束总得分为 mm 次取数得分之和。

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

    输入输出格式

    输入格式:

     

    输入文件包括 n+1n+1 行:

    第 11 行为两个用空格隔开的整数 nn 和 mm 。

    第 2~n+12 n+1 行为 n imes mn×m 矩阵,其中每行有 mm 个用单个空格隔开的非负整数。

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 
    2 3
    1 2 3
    3 4 2
    
    输出样例#1: 
    82

    说明

    NOIP 2007 提高第三题

    数据范围:

    60%的数据满足: 1le n, m le 301n,m30 ,答案不超过 10^{16}1016
    100%的数据满足: 1le n, m le 801n,m80 , 0 le a_{i,j} le 10000ai,j1000

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <math.h>
     5 #include <iostream>
     6 
     7 using namespace std;
     8 
     9 struct num {
    10     int a[35];
    11     num() { memset(a, 0, sizeof(a)); }
    12     num(int p) {
    13         memset(a, 0, sizeof(a));
    14         int i = 1;
    15         while (p != 0) {
    16             a[i] = p % 10;
    17             p /= 10;
    18             i++;
    19         }
    20         a[0] = i - 1;
    21     }
    22     num operator +(num b) {
    23         int l = max(a[0], b.a[0]);
    24         num c;
    25         for (int i = 1; i <= l; i++) {
    26             c.a[i] += a[i] + b.a[i];
    27             if (c.a[i] > 9) {
    28                 c.a[i + 1]++;
    29                 c.a[i] -= 10;
    30                 if (i == l)l++;
    31             }
    32         }
    33         c.a[0] = l;
    34         return c;
    35     }
    36     void print() {
    37         printf("%d", a[a[0]]);
    38         for (int i = a[0]-1; i >= 1; i--)
    39             printf("%d", a[i]);
    40         printf("
    ");
    41     }
    42 };
    43 bool operator <(num p,num b) {
    44     if (p.a[0] > b.a[0])
    45         return false;
    46     if (p.a[0] < b.a[0])
    47         return true;
    48     for (int i = p.a[0]; i >= 1; i--)
    49     {
    50         if (p.a[i] < b.a[i])
    51             return true;
    52         if (p.a[i] > b.a[i])
    53             return false;
    54     }
    55     return false;
    56 }
    57 
    58 num ans;
    59 int n, m;
    60 int mat[100];
    61 num dp[100][100];
    62 
    63 int main()
    64 {
    65     scanf("%d%d", &n, &m);
    66     for (int i = 1; i <= n; i++) {
    67         memset(dp, 0, sizeof(dp));
    68         for (int j = 1; j <= m; j++)
    69         {
    70             scanf("%d", &mat[j]);
    71             dp[j][j] = mat[j];
    72         }
    73         for(int j=2;j<=m;j++)
    74             for (int k = 1; k <= m - j + 1; k++) 
    75                 dp[k][k + j - 1] = max(dp[k][k + j - 1], max(num(mat[k]) + dp[k + 1][k + j - 1]+ dp[k + 1][k + j - 1], num(mat[k + j - 1]) + dp[k][k + j - 2]+ dp[k][k + j - 2]));
    76         ans =ans+dp[1][m]+dp[1][m];
    77     }
    78     ans.print();
    79     return 0;
    80 }
    View Code

    注意

    难点在于高精度。看到有人用int128但我并不会用orz。记得在计概课做过此题,当时数据没那么大……所以一开始写的版本全都没有考虑数据大到一定要用高精(int->long->ll->高精)

    高精度可以用mod进行优化,感觉好神奇(在我的代码中并未体现,回过头来再试试吧)

    很多人把0的情况单列了,其实不用,只要考虑到了在 print() 函数中稍作改动即可( line:37 )

    WA

    1.循环里没有重置dp…………debug了很久,感觉我好像总会发生这样的错误

    2.结构体里那个数组一定要开大,最大数据达到30位,我就开到30位……于是RE

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    让元素水平和垂直居中的方法总结
    a标签常见问题
    centos7的安装
    java面向对象-类的定义
    java内存划分
    java基础知识点-数组
    java基础知识点-重载
    第一章:服务器的组成知识点
    java 第二天运算符及录入函数Scanner
    java第一天 数据类型、变量的命名、类型的转换
  • 原文地址:https://www.cnblogs.com/yalphait/p/9378912.html
Copyright © 2011-2022 走看看