矩阵dp

矩阵dp

  这里是矩阵dp,不是矩阵乘法优化dp。

  矩阵上的dp好像也没什么特殊的?大概有一个套路就是从上向下,从左向右进行dp吧。


   

  首先第一道题好像不是矩阵dp...

  1005 矩阵取数游戏:https://www.luogu.org/problemnew/show/P1005

  题意概述:在一个矩阵里面取数,每次从每行的左或右取一个数,并乘以$2^i$,$i$是取数的次数。直到取完为止,求最大得分。

  看起来是道非常复杂的矩阵dp题,理性分析一下可以发现每一行之间并没有什么关系,所以分行做完以后再加起来就可以啦。那么在每一行内怎么做呢?像区间dp一样,用$dp[i][j]$表示取到剩下区间$[i][j]$时的最大得分。

  然后再加上高精...

  
  1 # include <cstdio>
  2 # include <iostream>
  3 # include <cstring>
  4 # define R register int
  5 
  6 using namespace std;
  7 
  8 int n,m,j;
  9 int len,a[81][81];
 10 int dp[81][81][1000];
 11 int P[81][100],ansc[81][1000],ans[1000];
 12 int t[1000];
 13 
 14 void add (int *a,int *b)
 15 {
 16     len=max(a[0],b[0])+2;
 17     for (R i=1;i<=len;++i)
 18     {
 19         a[i]+=b[i];
 20         a[i+1]+=a[i]/10;
 21         a[i]%=10;    
 22     }
 23     while (a[len]==0&&len) len--;
 24     a[0]=len;
 25 }
 26 
 27 void M (int *a,int *b)
 28 {
 29     if(a[0]>b[0]) return ;
 30     if(b[0]>a[0])
 31     {
 32         len=b[0];
 33         for (R i=0;i<=len;++i)
 34             a[i]=b[i];
 35         return ;
 36     }
 37     len=a[0];
 38     for (R i=len;i>=1;--i)
 39     {
 40         if(a[i]>b[i]) return ;
 41         if(a[i]==b[i]) continue;
 42         if(a[i]<b[i])
 43         {
 44             for (R j=0;j<=len;++j)
 45                 a[j]=b[j];
 46             return ;
 47         }
 48     }
 49 }
 50 
 51 void mul(int *a,int *b,int c)
 52 {
 53     len=b[0];
 54     for (R i=1;i<=len;++i)
 55         a[i]=b[i]*c;
 56     len+=3;
 57     for (R i=1;i<=len;++i)
 58         a[i+1]+=a[i]/10,a[i]%=10;
 59     while (a[len]==0&&len) len--;
 60     a[0]=len;
 61 }
 62 
 63 int main()
 64 {
 65     scanf("%d%d",&n,&m);
 66     P[0][0]=P[0][1]=1;
 67     for (R i=1;i<=80;++i)
 68     {
 69         P[i][0]=P[i-1][0]*2;
 70         len=P[i][0];
 71         for (R j=1;j<=len;++j)
 72             P[i][j]=P[i-1][j]*2;
 73         for (R j=1;j<=len;++j)    
 74             P[i][j+1]+=P[i][j]/10,P[i][j]%=10;
 75         while (P[i][len]==0&&len) len--;
 76         P[i][0]=len;
 77     }
 78     for (R i=1;i<=n;++i)
 79         for (R j=1;j<=m;++j)
 80             scanf("%d",&a[i][j]);
 81     for (R c=1;c<=n;++c)
 82     {
 83         memset(dp,0,sizeof(dp));
 84         memset(ansc,0,sizeof(ansc));
 85         for (R k=m;k>=1;k--)
 86             for (R i=1;i+k-1<=m;i++)
 87             {
 88                 j=i+k-1;
 89                 memset(t,0,sizeof(t));
 90                 mul(t,P[m-k+1],a[c][i]);
 91                 add(t,dp[i][j]);
 92                 M(dp[i+1][j],t);
 93                 memset(t,0,sizeof(t));
 94                 mul(t,P[m-k+1],a[c][j]);
 95                 add(t,dp[i][j]);
 96                 M(dp[i][j-1],t);
 97             }
 98         for (R i=1;i<=m;++i)
 99         {
100             mul(ansc[i],P[m],a[c][i]);
101             add(ansc[i],dp[i][i]);
102         }
103         for (R i=1;i<=m;++i)
104             M(ansc[1],ansc[i]);
105         add(ans,ansc[1]);
106     }
107     len=ans[0];
108     for (R i=len;i>=1;--i)
109         printf("%d",ans[i]);
110     if(len==0) printf("0");
111     return 0;
112 }
矩阵取数游戏

 

猜你喜欢

转载自www.cnblogs.com/shzr/p/9275261.html