noip2007 T3 矩阵取数(动归+操作符重载处理高精)
2016-10-25 20:04
302 查看
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij据为非负整数。游戏规则如下:
每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有的元素;
每次取走的各个元素只能是该元素所在行的行首或行尾;
每次取数都有一个得分值,为每行取数的得分之和;每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);
游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
Input Format
输入文件game.in包括n+1行;
第一行为两个用空格隔开的整数n和m。
第2~n+1行为n*m矩阵,其中每行有m个用单个空格隔开
Output Format
输出文件game.out仅包含1行,为一个整数,即输入矩阵取数后的最大的分。
Sample Input
【输入样例1】
2 3
1 2 3
3 4 2
【输入样例2】
1 4
4 5 0 5
【输入样例3】
2 10
96 56 54 46 86 12 23 88 80 43
16 95 18 29 30 53 88 83 64 67
Sample Output
输出样例1
82
输出样例2
122
输出样例3
316994
Hint
【输入输出样例1解释】
第1次:第一行取行首元素,第二行取行尾元素,本次的氛围1 * 2^1+2 * 2^1=6
第2次:两行均取行首元素,本次得分为2 * 2^2+3 * 2^2=20
第3次:得分为3 * 2^3+4 * 2^3=56。总得分为6+20+56=82
数据范围:
60%的数据满足:1<=n, m<=30,答案不超过10^16
100%的数据满足:1<=n, m<=80,0<=aij<=1000
显然是一行一行处理。
题目的m级别80,又是第三题,要考虑动归,可以4维;
一行中,我们每次只选一个,左边或右边一个,两边的数取来取来,中间的序列还没变,我们可以以剩余数的序列为状态。
f[i][j] 当前序列i到j,如果这一次取左边的数a[i]:f[i+1][j];
取右边的数a[j]:f[i][j-1];
幂为 m-j(右边已经取得个数)+i-1(左边已经取得个数)+1(现在还有取走一个)=m-j+i;
转移
用上高精,操作符重载处理的代码
有关操作符重载的详细博客:
http://blog.csdn.net/jtli_embeddedcv/article/details/10132791;
每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有的元素;
每次取走的各个元素只能是该元素所在行的行首或行尾;
每次取数都有一个得分值,为每行取数的得分之和;每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);
游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
Input Format
输入文件game.in包括n+1行;
第一行为两个用空格隔开的整数n和m。
第2~n+1行为n*m矩阵,其中每行有m个用单个空格隔开
Output Format
输出文件game.out仅包含1行,为一个整数,即输入矩阵取数后的最大的分。
Sample Input
【输入样例1】
2 3
1 2 3
3 4 2
【输入样例2】
1 4
4 5 0 5
【输入样例3】
2 10
96 56 54 46 86 12 23 88 80 43
16 95 18 29 30 53 88 83 64 67
Sample Output
输出样例1
82
输出样例2
122
输出样例3
316994
Hint
【输入输出样例1解释】
第1次:第一行取行首元素,第二行取行尾元素,本次的氛围1 * 2^1+2 * 2^1=6
第2次:两行均取行首元素,本次得分为2 * 2^2+3 * 2^2=20
第3次:得分为3 * 2^3+4 * 2^3=56。总得分为6+20+56=82
数据范围:
60%的数据满足:1<=n, m<=30,答案不超过10^16
100%的数据满足:1<=n, m<=80,0<=aij<=1000
显然是一行一行处理。
题目的m级别80,又是第三题,要考虑动归,可以4维;
一行中,我们每次只选一个,左边或右边一个,两边的数取来取来,中间的序列还没变,我们可以以剩余数的序列为状态。
f[i][j] 当前序列i到j,如果这一次取左边的数a[i]:f[i+1][j];
取右边的数a[j]:f[i][j-1];
幂为 m-j(右边已经取得个数)+i-1(左边已经取得个数)+1(现在还有取走一个)=m-j+i;
转移
if (f[j][k-1]<f[j][k]+v[i][k]*re(m-k+j)) f[j][k-1]=f[j][k]+v[i][k]*re(m-k+j); if (f[j+1][k]<f[j][k]+v[i][j]*re(m-k+j)) f[j+1][k]=f[j][k]+v[i][j]*re(m-k+j);
用上高精,操作符重载处理的代码
#include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #define INF 0x3f3f3f3f #define maxn 100 #define mod 10000 using namespace std; int n,m; int d[maxn]; struct data{ // 模板来自hjj int a[30]; void init(int x) { a[0]=1; a[1]=x; } void Printf() { printf("%d",a[a[0]]); for (int i=a[0]-1;i;--i) printf("%.4d",a[i]); } }ans,po[maxn],f[maxn][maxn]; data operator *(data A,int x) { A.a[A.a[0]+1]=0; for (int i=1;i<=A.a[0];i++) A.a[i]=A.a[i]*x; for (int i=1;i<=A.a[0];i++) if (A.a[i]>=mod) { A.a[i+1]+=A.a[i]/mod;//..... A.a[i]=A.a[i]%mod; } if (A.a[A.a[0]+1])++A.a[0]; return A; } bool operator <(data A,data B) //应该true是小于号,false大于号,相等的情况无所谓 函数类型应是bool { if(A.a[0]<B.a[0]) return true; if(A.a[0]>B.a[0]) return false; for (int i=A.a[0];i>=1;i--) { if (A.a[i]<B.a[i]) return true; if (A.a[i]>B.a[i]) return false; } return false; } data operator +(data A,data B) //加法异常爆炸 应该先加完在进位,或者位数爆炸? { int len=max(A.a[0],B.a[0]); le 4000 n=len; for (int i=A.a[0]+1;i<=len+1;i++) A.a[i]=0; for (int i=B.a[0]+1;i<=len+1;i++) B.a[i]=0; for (int i=1;i<=len;i++) { A.a[i]+=B.a[i]; } for (int i=1;i<=len;i++) if (A.a[i]>=mod) { A.a[i+1]=A.a[i+1]+1; A.a[i]=A.a[i]-mod; } if (A.a[len+1])A.a[0]=len+1; else A.a[0]=len; return A; } int main(){ scanf("%d%d",&n,&m); po[0].init(1); for (int i=1;i<=m;i++) po[i]=po[i-1]*2; for (data tmp;n;n--) { for (int i=0;i<=m;i++) for (int j=0;j<=m;j++) f[i][j].init(0); for (int i=1;i<=m;i++) scanf("%d",&d[i]); for (int i=1;i<=m;i++) { for (int j=m;j>=i;j--) { tmp=f[i][j]+po[m-j+i]*d[i]; if (f[i+1][j]<tmp)f[i+1][j]=tmp; tmp=f[i][j]+po[m-j+i]*d[j]; if (f[i][j-1]<tmp)f[i][j-1]=tmp; } tmp.init(0); for (int i=0;i<=m-1;i++) if (tmp<f[i+1][i]) tmp=f[i+1][i]; } ans=ans+tmp; } ans.Printf(); return 0; }
有关操作符重载的详细博客:
http://blog.csdn.net/jtli_embeddedcv/article/details/10132791;
相关文章推荐
- 【NOIP2007提高组T3】矩阵取数游戏-动态规划+高精度
- 【原题】【noip2007 T3】矩阵取数
- 洛谷 P1005 Tyvj P1054 [NOIP2007 T3] 矩阵取数游戏 [60分 非高精]
- 洛谷P1005&NOIP2007 矩阵取数游戏
- NOIP2007 矩阵取数游戏 [dp] [高精度]
- NOIP2007【矩阵取数游戏】
- NOIP2007 矩阵取数游戏
- Codevs_1166_[NOIP2007]_矩阵取数游戏_(动态规划+高精度)
- 【NOIP2007】矩阵取数题解
- NOIP2007提高组 矩阵取数
- 【NOIP2007】洛谷1005 矩阵取数游戏
- [NOIP2007] 矩阵取数游戏
- Noip 2007 矩阵取数游戏
- NOIP2007 提高组 复赛 game 矩阵取数游戏
- [NOIp2007提高组]矩阵取数游戏
- [NOIP2007] 提高组 洛谷P1005 矩阵取数游戏
- NOIP 2014 普及组 T3 螺旋矩阵
- ACM 96. [NOIP2007] 矩阵取数游戏(dp+高精度)
- NOIP2007 矩阵取数游戏
- NOIP2007 矩阵取数 DP+高精度