帥帥常常跟同窗玩一個矩陣取數遊戲:對於一個給定的n*m的矩陣,矩陣中的每一個元素aij均爲非負整數。遊戲規則以下:ios
1.每次取數時須從每行各取走一個元素,共n個。m次後取完矩陣全部元素;數組
2.每次取走的各個元素只能是該元素所在行的行首或行尾;spa
3.每次取數都有一個得分值,爲每行取數的得分之和,每行取數的得分 = 被取走的元素值*2^i,其中i表示第i次取數(從1開始編號);調試
4.遊戲結束總得分爲m次取數得分之和。code
帥帥想請你幫忙寫一個程序,對於任意矩陣,能夠求出取數後的最大得分。blog
輸入格式:遊戲
輸入文件game.in包括n+1行:ci
第1行爲兩個用空格隔開的整數n和m。string
第2~n+1行爲n*m矩陣,其中每行有m個用單個空格隔開的非負整數。io
數據範圍:
60%的數據知足:1<=n, m<=30,答案不超過10^16
100%的數據知足:1<=n, m<=80,0<=aij<=1000
輸出格式:
輸出文件game.out僅包含1行,爲一個整數,即輸入矩陣取數後的最大得分。
2 3 1 2 3 3 4 2
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); }