题目描述
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的 n \times mn×m 的矩阵,矩阵中的每个元素 Ai,j
均为非负整数。游戏规则如下:
每次取数时须从每行各取走一个元素,共 n 个。经过 m 次后取完矩阵内所有元素;
每次取走的各个元素只能是该元素所在行的行首或行尾;
每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值 2i×i ,其中 i 表示第 i 次取数(从 1 开始编号);
游戏结束总得分为 m 次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
输入格式
输入文件包括 n+1n+1 行:
第一行为两个用空格隔开的整数 n 和 m。
第 2∼n+1 行为 n×m 矩阵,其中每行有 m 个用单个空格隔开的非负整数。
输出格式
输出文件仅包含 11 行,为一个整数,即输入矩阵取数后的最大得分。
输入样例
2 3
1 2 3
3 4 2
输出样例
82
解题思路
基本区间动态规划。
设 f[i][j] 已经取完了当前行 1…i 和 j…m 的数字后的最大得分。
那么 f[i][j] 可以由两种方式转来。
1.最后取 a[i]
2.最后取 a[j]
方程:
f[i][j]=max(f[i-1][j]+a[i]*2(n-j+i+1),f[i][j+1]+a[j]*2(n-j+i+1));
但本题可以说最大的难点就是高精度,才在洛谷里面成了蓝题,因此在做的时候要注意高精度等细节。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct hun
{
int a[105],l;
}pow2[1005],ans,f[85][85],a[1005];
int n,m;
void getpow()
{
pow2[0]={
{
0,1},1};
for(int i=1;i<=1000;i++)
{
pow2[i].l=pow2[i-1].l;
for(int j=1;j<=pow2[i].l;j++)
{
pow2[i].a[j]+=pow2[i-1].a[j]*2