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 }

时间: 2024-10-14 09:50:54

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

1166 矩阵取数游戏[区间dp+高精度]

1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分

[luoguP1005] 矩阵取数游戏(DP + 高精度)

传送门 和奶牛那个题很像,每一行状态互不影响,也就是求 n 遍DP 不过高精度非常恶心,第一次写,调了我一上午. ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 struct Big_int 6 { 7 int s[35], idx; 8 Big_int() 9 { 10 idx = 0; 11 memset(s, 0, sizeof(s)); 12 } 13 }; 14 1

NOIP2007 矩阵取数游戏

题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i, 其中i 表示第i 次取数(从1 开始编号): 4. 游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个

Noip2007矩阵取数游戏题解

题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n?m的矩阵,矩阵中的每个元素ai,j均 为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 每次取走的各个元素只能是该元素所在行的行首或行尾: 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分=被取走的元素值?2i, 其中i表示第i 次取数(从1 开始编号): 游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出

洛谷 P1005 矩阵取数游戏 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1005 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元

矩阵取数游戏 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的压位,感觉

矩阵取数游戏

题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,其中i 表示第i 次取数(从1 开始编号):4. 游戏结束总得分为m次取数得分之和.帅帅想请你帮忙写一个程序,对于任意矩

P1005矩阵取数游戏

题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入输

矩阵取数游戏洛谷p1005

题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入输