18.7.27 luogu P1005 矩阵取数游戏

题目描述

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

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

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

输入输出格式

输入格式:

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

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

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

输出格式:

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

输入输出样例

输入样例#1:

2 3
1 2 3
3 4 2

输出样例#1:

82

说明

NOIP 2007 提高第三题

数据范围:

60%的数据满足: 1\le n, m \le 301≤n,m≤30 ,答案不超过 10^{16}1016
100%的数据满足: 1\le n, m \le 801≤n,m≤80 , 0 \le a_{i,j} \le 10000≤ai,j?≤1000

 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("\n");
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 }

注意

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

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

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

WA

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

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

原文地址:https://www.cnblogs.com/yalphait/p/9378912.html

时间: 2024-11-08 20:44:25

18.7.27 luogu P1005 矩阵取数游戏的相关文章

luogu P1005 矩阵取数游戏 区间DP

每一行是独立的,分开处理即可. dp[i][j]表示[i,j]这一段,取完的最大收益.转移很显然,dp[i][j] = max(dp[i + 1][j] + 2^(m - (j - l)) * mp[t][i],dp[i][j - 1] + 2^(m - (j - l)) * mp[t][j]) 不想写高精度,python水一发. 1 n,m = map(int,input().split()) 2 res = 0 3 mp = [[0 for i in range(0,80,1)] for i

P1005 矩阵取数游戏

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

洛谷P1005 矩阵取数游戏

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

洛谷 P1005 矩阵取数游戏 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1005 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元

P1005矩阵取数游戏

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

洛谷 P1005 矩阵取数游戏

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

[LuoguP1005]矩阵取数游戏 (DP+高精度)

题面 传送门:https://www.luogu.org/problemnew/show/P1005 Solution 我们可以先考虑贪心 我们每一次都选左右两边尽可能小的数,方便大的放在后面 听起来挺OK的 实则并不OK 反例: 3 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 如果贪心的话,我们会优先把右边那一串2先选了,再去选3和1 但是正确答案显然是先把3和1选了,再去选那一串2 既然贪心不成,我们可以考虑一下DP 然后我们考虑这样一个状态: f[i][j][k] 表示第i

矩阵取数游戏洛谷p1005

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

AC日记——矩阵取数游戏 洛谷 P1005

矩阵取数游戏 思路: dp+高精: 代码: #include <bits/stdc++.h> using namespace std; #define ll long long struct Int { int len; char ai[300]; Int() { len=1,ai[0]=0; } void Count(int pos) { len++; if(pos/10) Count(pos/10); } void operator=(int pos_) { int pos=pos_; l