题目描述
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:
1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
2.每次取走的各个元素只能是该元素所在行的行首或行尾;
3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);
4.游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
输入输出格式
输入格式:
输入文件game.in包括n+1行:
第1行为两个用空格隔开的整数n和m。
第2~n+1行为n*m矩阵,其中每行有m个用单个空格隔开的非负整数。
数据范围:
60%的数据满足:1<=n, m<=30,答案不超过10^16
100%的数据满足:1<=n, m<=80,0<=aij<=1000
输出格式:
输出文件game.out仅包含1行,为一个整数,即输入矩阵取数后的最大得分。
贪心地去取每行不一定最优--
用区间dp,,f[i][j]:左边取到i右边取到j最优解
高精度运算
记得特判输出0。。。GG
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 101;
struct data{
int len,a[maxn];
data() {len = 0; memset(a,0,sizeof(a));}
data operator = (const int &k) {
len = 0;
int K = k;
while (K) {
a[len++] = K % 10;
K /= 10;
}
}
data operator + (const data &b) {
data c;
int Len = max(len,b.len);
for (int i = 0; i < Len; i++) {
c.a[i] += a[i] + b.a[i];
c.a[i + 1] += c.a[i] / 10;
c.a[i] %= 10;
}
c.len = c.a[Len]?Len+1:Len;
return c;
}
data operator * (const data &b) {
data c;
for (int i = 0; i < len; i++)
for (int j = 0; j < b.len; j++) {
int TT = a[i];
c.a[i+j] += a[i]*b.a[j];
c.a[i+j+1] += c.a[i+j] / 10;
c.a[i+j] %= 10;
}
c.len = c.a[len+b.len-1]?len+b.len:len+b.len-1;
return c;
}
bool operator < (const data &b) {
if (len < b.len) return 1;
if (len > b.len) return 0;
for (int i = len - 1; i >= 0; i--) {
if (a[i] < b.a[i]) return 1;
if (a[i] > b.a[i]) return 0;
}
return rand()%2;
}
}ans,t[maxn][maxn],f[maxn][maxn],two[maxn];
int n,m;
void Solve(int k)
{
for (int i = 0; i <= m; i++)
for (int j = m + 1; j > i; j--) {
f[i][j] = 0;
int ti = i + m - j + 1;
if (i) f[i][j] = f[i-1][j] + two[ti]*t[k][i];
if (j <= m) {
data now = f[i][j+1] + two[ti]*t[k][j];
if (f[i][j] < now) f[i][j] = now;
}
}
data Max; Max = 0;
for (int i = 0; i <= m; i++)
if (Max < f[i][i+1])
Max = f[i][i+1];
ans = ans + Max;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
int x; scanf("%d",&x);
t[i][j] = x;
}
two[1] = 2;
for (int i = 2; i <= m; i++)
two[i] = two[i-1]*two[1];
for (int i = 1; i <= n; i++)
Solve(i);
if (!ans.len) {puts("0"); return 0;}
for (int i = ans.len - 1; i >= 0; i--)
printf("%d",ans.a[i]);
return 0;
}