矩阵取数游戏 NOIP 2007
Posted Neptune
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵取数游戏 NOIP 2007相关的知识,希望对你有一定的参考价值。
2016-05-31 17:26:45
题目链接: NOIP 2007 矩阵取数游戏(Codevs)
题目大意:
给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数
解法:
动态规划
DP[i][j]表示当前行i位置到j位置获得的最大分数
转移方程:
DP[i][j]=max(DP[i+1][j]+a[i]*2^x,DP[i][j-1]+a[i]*2^x);
需要注意的地方:
1.M和N给的范围略坑啊,2^80只有悄悄不说话了,所以直接上了100000的压位,感觉比高精好使多了
2.2的次方多次用到,所以预先处理出来待用
1 //矩阵取数游戏 (NOIP2007) 2 //动态规划 高精度 3 #include<stdio.h> 4 #include<algorithm> 5 #include<string.h> 6 using namespace std; 7 const int maxn=85; 8 const int maxm=85; 9 const int maxl=30; 10 int N,M; 11 int a[maxn]; 12 int DP[maxn][maxm][maxl]; 13 int ys[maxn][maxl]; 14 int ans[maxl]; 15 int tmp[maxl]; 16 void Multi(int *x,int *y,int z) 17 { 18 memset(tmp,0,sizeof(tmp)); 19 tmp[0]=y[0]; 20 for(int i=1;i<=tmp[0];i++) 21 { 22 tmp[i]=y[i]*z; 23 } 24 for(int i=1;i<=tmp[0];i++) 25 { 26 tmp[i+1]+=tmp[i]/100000; 27 tmp[i]%=100000; 28 } 29 while(tmp[tmp[0]+1]) 30 { 31 tmp[0]++; 32 tmp[tmp[0]+1]+=tmp[tmp[0]]/100000; 33 tmp[tmp[0]]%=100000; 34 } 35 for(int i=0;i<30;i++)x[i]=tmp[i]; 36 return ; 37 } 38 void Add(int *x,int *y,int *z) 39 { 40 memset(tmp,0,sizeof(tmp)); 41 if(y[0]>z[0])tmp[0]=y[0]; 42 else tmp[0]=z[0]; 43 for(int i=1;i<=tmp[0];i++) 44 { 45 tmp[i]=y[i]+z[i]; 46 } 47 for(int i=1;i<=tmp[0];i++) 48 { 49 tmp[i+1]+=tmp[i]/100000; 50 tmp[i]%=100000; 51 } 52 if(tmp[tmp[0]+1])tmp[0]++; 53 for(int i=0;i<30;i++)x[i]=tmp[i]; 54 return ; 55 } 56 bool Max(int *x,int *y) 57 { 58 if(x[0]>y[0])return 1; 59 else if(y[0]>x[0])return 0; 60 else 61 { 62 for(int i=x[0];i>=1;i--) 63 { 64 if(x[i]>y[i])return 1; 65 else if(x[i]<y[i])return 0; 66 } 67 } 68 return 1; 69 } 70 int main() 71 { 72 scanf("%d %d",&N,&M); 73 ys[0][0]=1; 74 ys[0][1]=1; 75 for(int i=1;i<=M;i++) 76 { 77 Multi(ys[i],ys[i-1],2); 78 } 79 ans[0]=1;ans[1]=0; 80 for(int i=1;i<=N;i++) 81 { 82 for(int j=1;j<=M;j++) 83 { 84 scanf("%d",&a[j]); 85 Multi(DP[j][j],ys[M],a[j]); 86 } 87 for(int k=2;k<=M;k++) 88 { 89 for(int x=1;x<=M-k+1;x++) 90 { 91 int y=x+k-1; 92 int xm[31],ym[31],cm[31]; 93 Multi(cm,ys[M-k+1],a[x]); 94 Add(xm,cm,DP[x+1][y]); 95 Multi(cm,ys[M-k+1],a[y]); 96 Add(ym,cm,DP[x][y-1]); 97 if(Max(xm,ym)) 98 { 99 memcpy(DP[x][y],xm,sizeof(int)*30); 100 } 101 else 102 { 103 memcpy(DP[x][y],ym,sizeof(int)*30); 104 } 105 } 106 } 107 Add(ans,ans,DP[1][M]); 108 } 109 printf("%d",ans[ans[0]]); 110 for(int i=ans[0]-1;i>=1;i--) 111 { 112 printf("%05d",ans[i]); 113 } 114 printf("\n"); 115 return 0; 116 }
以上是关于矩阵取数游戏 NOIP 2007的主要内容,如果未能解决你的问题,请参考以下文章
dp+高精度(洛谷1005 矩阵取数游戏NOIP 2007 提高第三题)
P1005 [NOIP2007 提高组] 矩阵取数游戏(区间dp)