洛谷 1005 矩阵取数游戏
Posted ovo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 1005 矩阵取数游戏相关的知识,希望对你有一定的参考价值。
Description
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下:
1.每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
2.每次取走的各个元素只能是该元素所在行的行首或行尾;
3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);
4.游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
Input
输入文件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
Output
输出文件game.out仅包含1行,为一个整数,即输入矩阵取数后的最大得分。
Sample
输入样例#1:
2 3
1 2 3
3 4 2
输出样例#1:
82
Hints
NOIP 2007 提高第三题
Solution
简单的dp,高精好麻烦,不知道为什么跑得特别特别慢
大整数赋值的时候,要记得清0
重载的时候大于号和小于号不一样
哪位大佬告诉我为什么跑得这么慢
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; const int nn=83; int n,m,a[nn]; struct bn{ int len,v[32]; bn(){len=0;memset(v,0,sizeof(v));} bool operator <(const bn &x)const { //<>分开重载 if(len!=x.len) return len<x.len; for(int i=len;i>=1;i--) if(v[i]!=x.v[i]) return v[i]<x.v[i]; return 0; } bn& operator*(bn x) { bn res; res.len=len+x.len; for(int i=1;i<=len;i++) for(int j=1;j<=x.len;j++) { res.v[i+j-1]+=v[i]*x.v[j]; res.v[i+j]+=res.v[i+j-1]/10; res.v[i+j-1]=res.v[i+j-1]%10; } while(res.len>1&&!res.v[res.len]) res.len--; return res; } bn& operator=(int x) { len=0; //////////////// memset(v,0,sizeof(v)); ///////////// while(x) { v[++len]=x%10; x/=10; } len=len==0? 1:len; return *this; } bn& operator=(bn x) { len=x.len; for(int i=1;i<=31;i++) v[i]=x.v[i]; return *this; } bn& operator+(bn x){ bn res; res.len=max(len,x.len)+1; for(int i=1;i<=res.len;i++) { res.v[i]+=v[i]+x.v[i]; res.v[i+1]+=res.v[i]/10; res.v[i]%=10; } while(res.len>1&&!res.v[res.len]) res.len--; return res; } }two,dp[nn][nn],mi[nn]; inline int read() { register int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch==\'-\') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-\'0\';ch=getchar();} return ans*f; } bn solve(int h) { bn ans,zc,ta; for(register int i=1;i<=m;++i) for(register int j=i;j<=m;++j) dp[i][j]=0; // memset(dp,0,sizeof(dp)); for(register int i=m-1;i>=1;--i) for(register int j=1;j<=m-i+1;++j) { if(j-1>=1) { ta=a[j-1]; zc=dp[j-1][j+i-1]+ta*mi[m-i]; if(dp[j][j+i-1]<zc) dp[j][j+i-1]=zc; } if(j+i<=m) { ta=a[i+j]; zc=dp[j][i+j]+ta*mi[m-i]; if(dp[j][i+j-1]<zc) dp[j][j+i-1]=zc; } } for(register int i=1;i<=m;++i) { ta=a[i]; dp[i][i]=dp[i][i]+ta*mi[m]; if(ans<dp[i][i]) ans=dp[i][i]; } return ans; } int main() { two=2; bn res; n=read();m=read(); mi[0]=1; for(register int i=1;i<=m;++i) mi[i]=mi[i-1]*two; for(register int i=1;i<=n;++i) { for(register int j=1;j<=m;++j) a[j]=read(); res=res+solve(i); } for(register int i=res.len;i>=1;--i) putchar(res.v[i]+\'0\'); return 0; }
以上是关于洛谷 1005 矩阵取数游戏的主要内容,如果未能解决你的问题,请参考以下文章