Codevs_1166_[NOIP2007]_矩阵取数游戏_(动态规划+高精度)

描述


http://codevs.cn/problem/1166/

分析


  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int maxn=50;
  8 
  9 struct Bign{
 10     int x[maxn],cnt;
 11     int & operator [] (int id){ return x[id]; }
 12     Bign(){ memset(x,0,sizeof x); }//空的构造函数
 13     Bign(int num){ *this=num; }//赋一个数字的构造函数
 14     Bign(char* num){ *this=num; }//赋一个字符串数字的构造函数
 15     Bign operator = (const char* num){//字符串的赋值函数
 16         memset(x,0,sizeof x); cnt=strlen(num);
 17         for(int i=1;i<=cnt;i++) x[i]=num[cnt-i-1]-'0';
 18         return *this;
 19     }
 20     Bign operator = (int num){//数字的赋值函数
 21         memset(x,0,sizeof x); cnt=0;
 22         while(num){
 23             x[++cnt]=num%10;
 24             num/=10;
 25         }
 26         return *this;
 27     }
 28     Bign operator + (Bign y) const{//加法
 29         Bign z; z.cnt=max(cnt,y.cnt);
 30         for(int i=1;i<=z.cnt;i++){
 31             z[i]+=x[i]+y[i];
 32             if(z[i]>=10) z[i+1]++, z[i]-=10;
 33         }
 34         if(z[z.cnt+1]) z.cnt++;//加法至多多出一位
 35         return z;
 36     }
 37     Bign operator - (Bign y) const{//减法
 38         Bign z; z.cnt=cnt;
 39         for(int i=1;i<=z.cnt;i++){
 40             z[i]+=x[i]-y[i];
 41             if(z[i]<0) z[i+1]--, z[i]+=10;
 42         }
 43         while(z.cnt&&!z[z.cnt]) z.cnt--;//减法可能会少很多位
 44         return z;
 45     }
 46      Bign operator * (Bign y) const{//乘法
 47         Bign z;
 48         for(int i=1;i<=cnt;i++)
 49             for(int j=1;j<=y.cnt;j++)
 50                 z[i+j-1]+=x[i]*y[j],z[i+j]+=z[i+j-1]/10, z[i+j-1]%=10;
 51         z.cnt=cnt+y.cnt;//乘法后结果的位数为cnt1+cnt2或cnt1+cnt2-1.
 52         if(!z[z.cnt]) z.cnt--;
 53         return z;
 54     }
 55     Bign operator / (Bign y) const{//除法
 56         Bign z=*this,d=0;
 57         for(int i=cnt;i;i--){
 58             d=d*10+x[i];
 59             for(int j=0;j<10;j++)
 60                 if(d<y*(j+1)){
 61                     z[i]=j;
 62                     d=d-y*j;
 63                     break;
 64                 }
 65         }
 66         while(z.cnt&&!z[z.cnt]) z.cnt--;
 67         return z;
 68     }
 69     Bign operator % (Bign y) const{//取模
 70         Bign d=0;
 71         for(int i=cnt;i;i--){
 72             d=d*10+x[i];
 73             for(int j=0;j<10;j++)
 74                 if(d<y*(j+1)){
 75                     d=d-y*j;
 76                     break;
 77                 }
 78         }
 79         return d;
 80     }
 81     Bign &operator += (Bign y){ *this=*this+y; return *this; }
 82     Bign &operator -= (Bign y){ *this=*this-y; return *this; }
 83     Bign &operator *= (Bign y){ *this=*this*y; return *this; }
 84     Bign &operator /= (Bign y){ *this=*this/y; return *this; }
 85     Bign &operator %= (Bign y){ *this=*this%y; return *this; }
 86 
 87     bool operator < (Bign y){
 88         if(cnt!=y.cnt) return cnt<y.cnt;
 89         for(int i=cnt;i;i--)
 90             if(x[i]!=y[i]) return x[i]<y[i];
 91         return false;
 92     }
 93     bool operator > (Bign y){ return y<*this; }
 94     bool operator <= (Bign y){ return!(y<*this); }
 95     bool operator >= (Bign y){ return!(*this<y); }
 96     bool operator != (Bign y){ return y<*this||*this<y; }
 97     bool operator == (Bign y){ return!(y<*this)&&!(*this<y); }
 98 }dp[100][100],a[100][100],ans;
 99 istream& operator >> (istream &in,Bign &x){//输入
100     char s[maxn];
101     scanf("%s",s+1); int len=strlen(s+1);
102     for(int i=len;i;i--)
103         x[len+1-i]=s[i]-'0';
104     x.cnt=len;
105     return in;
106 }
107 ostream& operator << (ostream &out,Bign &x){//输出
108     for(int i=x.cnt;i;i--)
109         out << x[i];
110     if(!x.cnt) out << 0;
111     return out;
112 }
113 
114 int main(){
115     int n,m;
116     scanf("%d%d",&n,&m);
117     Bign t=1;
118     for(int i=1;i<=m;i++) t*=2;
119     for(int i=1;i<=n;i++){
120         memset(dp,0,sizeof dp);
121         for(int j=1;j<=m;j++){
122             cin >> a[i][j];
123             dp[j][j]=t*a[i][j];
124         }
125         Bign tmp=t;
126         for(int k=2;k<=m;k++){
127             tmp/=2;
128             for(int l=1;l<=m-k+1;l++){
129                 int r=l+k-1;
130                 if(dp[l+1][r]+a[i][l]*tmp>dp[l][r-1]+a[i][r]*tmp)
131                     dp[l][r]=dp[l+1][r]+a[i][l]*tmp;
132                 else
133                     dp[l][r]=dp[l][r-1]+a[i][r]*tmp;
134             }
135         }
136         ans+=dp[1][m];
137     }
138     cout << ans <<endl;
139     return 0;
140 }
View Code
原文地址:https://www.cnblogs.com/Sunnie69/p/5554758.html