Codevs_1166_[NOIP2007]_矩阵取数游戏_(动态规划+高精度)
Posted 晴歌。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于Codevs_1166_[NOIP2007]_矩阵取数游戏_(动态规划+高精度)的主要内容,如果未能解决你的问题,请参考以下文章
Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)