题目描述
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的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行,为一个整数,即输入矩阵取数后的最大得分。
输入输出样例
输入样例#1:
2 3 1 2 3 3 4 2
输出样例#1:
82
说明
NOIP 2007 提高第三题
-------------------------------------
DP
行与行之间相互独立,各行单独求解;一定先清空
f(i,j)左选了i个,右选了j个的最大得分
状态转移很好想,注意边界处理
高精度[这次从数组1开始]
高加高,高乘低
输出时一定小心0
建议先写出long long 的方便调试
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=85; const int B=1e4,L=100; struct big{ int size,d[L]; big(int a=1):size(a){memset(d,0,sizeof(int)*L);} }; void jia(big &a,big &b){ int g=0,i; for(i=1;;i++){ if(g==0&&i>a.size&&i>b.size) break; int tmp=g; if(i<=a.size) tmp+=a.d[i]; if(i<=b.size) tmp+=b.d[i]; a.d[i]=tmp%B; g=tmp/B; } a.size=i-1; } void chengInt(big &a,int k){ int g=0,i; for(i=1;i<=a.size;i++){ int tmp=a.d[i]*k; a.d[i]=(tmp+g)%B; g=(tmp+g)/B; } while(g){ a.d[++a.size]=g%B; g/=B; } } void copy(big &t,big &s){ t.size=s.size; for(int i=1;i<=s.size;i++) t.d[i]=s.d[i]; } big max(big &a,big &b){ if(a.size>b.size) return a; if(a.size<b.size) return b; for(int i=a.size;i>=1;i--){ if(a.d[i]>b.d[i]) return a; if(a.d[i]<b.d[i]) return b; } return a; } void print(big &a){ for(int i=a.size;i>=1;i--){ if(i==a.size); else if(a.d[i]<10) cout<<"0000"; else if(a.d[i]<100) cout<<"00"; else if(a.d[i]<1000) cout<<"0"; cout<<a.d[i]; } cout<<"\n"; } int n,m; int a[N][N]; big f[N][N]; big ans,fin=0; big two[N]; void PRE(){ two[0].d[1]=1; for(int i=1;i<=m+1;i++){ copy(two[i],two[i-1]); chengInt(two[i],2); } } big sol(int num){ ans=big(); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f[i][j]=big(); f[1][0].d[1]=a[num][1]*2; f[0][1].d[1]=a[num][m]*2; for(int i=2;i<=m;i++){ // f[i][0]=f[i-1][0]+a[num][i]*((ll)1<<i); // f[0][i]=f[0][i-1]+a[num][m-i+1]*((ll)1<<i); copy(f[i][0],f[i-1][0]); big tmp; copy(tmp,two[i]); chengInt(tmp,a[num][i]); jia(f[i][0],tmp); copy(f[0][i],f[0][i-1]); big tmp2; copy(tmp2,two[i]); chengInt(tmp2,a[num][m-i+1]); jia(f[0][i],tmp2); } for(int i=1;i<=m;i++) for(int j=1;j<=m-i;j++){ // f[i][j]=max(f[i-1][j]+a[num][i]*((ll)1<<(i+j)), // f[i][j-1]+a[num][m-j+1]*((ll)1<<(i+j))); big x,y; copy(x,f[i-1][j]); big tmp; copy(tmp,two[i+j]); chengInt(tmp,a[num][i]); jia(x,tmp); copy(y,f[i][j-1]); big tmp2; copy(tmp2,two[i+j]); chengInt(tmp2,a[num][m-j+1]); jia(y,tmp2); f[i][j]=max(x,y); } for(int i=0;i<=m;i++) ans=max(ans,f[i][m-i]); return ans; } int main(){//system("pause"); cin>>n>>m; PRE(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j]; for(int i=1;i<=n;i++) {big tmp=sol(i);jia(fin,tmp);} print(fin); }
时间: 2024-10-05 14:44:03