这道题大部分时间都在弄高精度……

还是先讲讲dp吧

这道题是一个区间dp,不过我还是第一次遇到这种类型的区间dp

f[i][j]表示取了数之后剩下i到j这个区间的最优值

注意这里是取了i之前和j之后的,i到j的数并没有取。

那么这个状态要不是取了第i-1个数转移而来,要不是取了第j+1个数转移而来。

所以可以写出方程 f[i][j] = max(f[i-1][j] + a[i-1] * mi[m-j+i-1], f[i][j+1] + a[j+1] * mi[m-j+i-1]);

然后注意这个区间dp是从大区间推到小区间,不一样。所以枚举的时候要注意区间是从大到小

ans = max(f[i][i] + mi[m])

然后这道题要用高精度。

注意不需要写高精*高精,可以写低精*高精

然后加法那里当前位数一定是+=,因为当前位数可能包含了进位

还要注意位数的调整

这里我弄了好久好久。我干脆趁这个机会搞个模板出来。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define REP(i, a, b) for(int i = (a); i < (b); i++)
  5. #define _for(i, a, b) for(int i = (a); i <= (b); i++)
  6. using namespace std;
  7. const int MAXN = 112;
  8. const int base = 10000;
  9. struct node
  10. {
  11. int len, s[505]; //s的范围开太大空间会炸
  12. node() { len = 0; memset(s, 0, sizeof(s)); }
  13. void print()
  14. {
  15. printf("%d", s[len]); //注意第一位不用补0
  16. for(int i = len - 1; i >= 1; i--)
  17. printf("%04d", s[i]);
  18. puts("");
  19. }
  20. }f[MAXN][MAXN], mi[MAXN];
  21. int a[MAXN], n, m;
  22. node operator + (const node& a, const node& b)
  23. {
  24. node c;
  25. int& len = c.len = max(a.len, b.len);
  26. _for(i, 1, len)
  27. {
  28. c.s[i] += a.s[i] + b.s[i]; //这里一定是+=,不是=
  29. c.s[i+1] += c.s[i] / base;
  30. c.s[i] %= base;
  31. }
  32. if(c.s[len+1] > 0) c.len++;
  33. return c;
  34. }
  35. node operator * (const int& a, const node& b)
  36. {
  37. node c;
  38. int& len = c.len = b.len;
  39. _for(i, 1, b.len)
  40. {
  41. c.s[i] += b.s[i] * a;
  42. c.s[i+1] += c.s[i] / base;
  43. c.s[i] %= base;
  44. }
  45. while(c.s[len+1] > 0) //进位是这么进位的
  46. {
  47. c.len++;
  48. c.s[len+1] += c.s[len] / base;
  49. c.s[len] %= base;
  50. }
  51. return c;
  52. }
  53. node max(node a, node b)
  54. {
  55. if(a.len > b.len) return a;
  56. else if(a.len < b.len) return b;
  57. else
  58. {
  59. for(int i = a.len; i >= 1; i--)
  60. {
  61. if(a.s[i] > b.s[i]) return a;
  62. else if(a.s[i] < b.s[i]) return b;
  63. }
  64. return a;
  65. }
  66. }
  67. int main()
  68. {
  69. mi[0].s[1] = 1; mi[0].len = 1;
  70. _for(i, 1, 80) mi[i] = 2 * mi[i-1];
  71. scanf("%d%d", &n, &m);
  72. node ans;
  73. _for(k, 1, n)
  74. {
  75. memset(f, 0, sizeof(f));
  76. _for(i, 1, m) scanf("%d", &a[i]);
  77. _for(i, 1, m)
  78. for(int j = m; j >= i; j--)
  79. f[i][j] = max(f[i-1][j] + a[i-1] * mi[m-j+i-1], f[i][j+1] + a[j+1] * mi[m-j+i-1]);
  80. node maxt; //为0就直接初始化就好了
  81. _for(i, 1, m)
  82. maxt = max(maxt, f[i][i] + a[i] * mi[m]);
  83. ans = ans + maxt;
  84. }
  85. ans.print();
  86. return 0;
  87. }

洛谷 P1005 矩阵取数游戏 (区间dp+高精度)的更多相关文章

  1. P1005 矩阵取数游戏 区间dp 高精度

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n \times mn×m的矩阵,矩阵中的每个元素a_{i,j}ai,j​均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n ...

  2. 洛谷P1005 矩阵取数游戏

    P1005 矩阵取数游戏 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次 ...

  3. [NOIP2007] 提高组 洛谷P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  4. 洛谷 P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  5. P1005 矩阵取数游戏[区间dp]

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(m*n\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.经过m次后 ...

  6. 1166 矩阵取数游戏[区间dp+高精度]

    1166 矩阵取数游戏 2007年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description [ ...

  7. P1005 矩阵取数游戏(动态规划+高精度)

    题目链接:传送门 题目大意: 给定长度为m的数列aj,每次从两端取一个数,得到2k * aj的价值(k为当前的次数,从1开始到m),总共有n行这样的数列,求最大价值总和. 1 ≤ n, m ≤ 80, ...

  8. [luoguP1005] 矩阵取数游戏(DP + 高精度)

    传送门 和奶牛那个题很像,每一行状态互不影响,也就是求 n 遍DP 不过高精度非常恶心,第一次写,调了我一上午. ——代码 #include <cstdio> #include <c ...

  9. 【洛谷P1288】取数游戏II

    取数游戏II 题目链接 显然,由于一定有一个0,我们可以求出从初始点到0的链的长度 若有一条链长为奇数,则先手可以每次取完一条边上所有的数, 后手只能取另一条边的数,先手必胜: 反之若没有奇数链,后手 ...

随机推荐

  1. laravel 授权、用户验证

    记录帖 一.授权 只允许管理员删除用户,给管理员授权时,可以这样做,首先: 创建UserPolicy类: php artisan make:policy UserPolicy  然后在UserPoli ...

  2. JS DOM 实例(5大常用实例)

    第1个实例:循环单击变色 <html lang="en"> <head> <meta charset="UTF-8"> &l ...

  3. js兼容性——获取当前浏览器窗口的宽高

    通过onresize事件 window.onresize = function () { document.title = client().width + " "+ client ...

  4. Linux 0.11中write实现

    看了一下Linux 0.11版本号write的实现,首先它在标准头文件unistd.h中有定义 int write(int fildes, const char * buf, off_t count) ...

  5. C++模板中的静态

    #include <iostream> #include <stdlib.h> using namespace std; template<class T> cla ...

  6. shadowOffset 具体解释

    x向右为正,y向下为正 1.y<0 UILabel *label=[[UILabelalloc] initWithFrame:CGRectMake(40,40, 250,50)]; label. ...

  7. JavaScript-4.4函数递归之阶乘举例---ShinePans

    <html> <head> <meta http-equiv="content-type" content="text/html;chars ...

  8. bzoj4868: [Shoi2017]期末考试(三分法)

    4868: [Shoi2017]期末考试 题目:传送门 题解: Get到一个新姿势...三分法 一开始百度百科的时候下了一跳...中国...的根??? 学懂了之后其实运用起来就根二分差不多啊,不过证明 ...

  9. codeblocks开源的c、c++编译器,小巧方便

    1.下载带gun的版本 2.设置编译的位置 3.创建项目 4.执行项目 有意思的开源的c编译器 ~~~

  10. MLPclassifier,MLP 多层感知器的的缩写(Multi-layer Perceptron)

    先看代码(sklearn的示例代码): from sklearn.neural_network import MLPClassifier X = [[0., 0.], [1., 1.]] y = [0 ...