【NOIP考前题目回顾】Luogu P1005
2017-10-29 20:15
225 查看
思路
这道题出题的初衷之一是考高精度,但是如果使用C++的__int128_t类型的话就可以不用高精度了。这道题显然是DP。先预处理出了一个数组Pi来存放2i,至于不用1<<i的原因是这些数太大了。然后我们考虑对于每一行,我们在处理一行的时候,最佳策略同上面某行下面某行没有任何关系,所以一行一行处理。那么方程就很简单了。令fi,j表示在每一行中还剩下区间[i,j]时的最大价值,最后累加就好了。代码
#include <cstdio> #include <cstring> #include <iostream> std::ostream& operator<<(std::ostream &dest, const __int128_t value) // 因为C++并没有给__int128_t重载流输入输出,所以cout需要我们自己写。 { std::ostream::sentry S(dest); if (S) { __uint128_t tmp = value < 0 ? -value : value; char buffer[129]; char* d = buffer + 129; char* d2 = d; do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (value < 0) { --d; *d = '-'; } int len = d2 - d; if (dest.rdbuf()->sputn(d, len) != len) dest.setstate(std::ios_base::badbit); } < c413 span class="hljs-keyword">return dest; } typedef __int128_t lll; int n,m; lll ans=0; int a[100]={0}; lll f[100][100]; lll p[100]={1}; lll dp() { memset(f, 0, sizeof f); for (int i = 1; i <= m; i++) for (int j = m; j >= i; j--) f[i][j] = std::max(f[i - 1][j] + p[m - j + i - 1] * a[i - 1] , f[i][j + 1] + p[m - j + i - 1] * a[j + 1]); lll maxn = -1; for (int i = 1; i <= m; i++) maxn = std::max(maxn, f[i][i] + a[i] * p[m]); return maxn; } int main() { for (int i = 1; i <= 90; i++) p[i] = p[i - 1] << 1; scanf("%d%d", &n, &m); for (int i=1;i<=n;i++) { for (int j = 1; j <= m; j++) scanf("%d", a + j); ans += dp(); } if (ans == 0) puts("0"); else std::cout << ans << std::endl; #ifdef __EDWARD_EDIT std::cin.get(); std::cin.get(); #endif return 0; }
相关文章推荐
- 【NOIP考前题目回顾】Luogu P1005
- 【NOIP考前题目回顾】Luogu P1000
- 【NOIP考前题目回顾】Luogu P1001
- 【NOIP考前题目回顾】Luogu P1040
- 【NOIP考前题目回顾】Luogu P1003
- 【NOIP考前题目回顾】Luogu P1046
- 【NOIP考前题目回顾】Luogu P1006
- 【NOIP考前题目回顾】Luogu P1047
- 【NOIP考前题目回顾】Luogu P1012
- NOIP2005试题题目名称
- [NOIP2017 考前胡写]一年以来犯的各种无脑错误与经验总结
- NOIP2009题目汇总
- NOIP2006题目汇总
- NOIP2003题目汇总
- ◆竞赛题目◆◇NOIP 2017 普及组◇ Chess 棋盘
- 竞赛题目讲解-【NOIP2000提高组】乘积最大
- 【2015自招必备】NOIP普及组完善程序题目汇编(含答案)
- 题目:[NOIP 2011]选择客栈
- 面试题目回顾6
- NOIP2005题目汇总