【NOIP2007提高组T3】矩阵取数游戏-动态规划+高精度
来源:互联网 发布:松下网络摄像机出厂ip 编辑:程序博客网 时间:2024/06/08 09:57
(本人本题完成于2016-7-20)
题目大意:对一个n行m列(1≤n,m≤80)的矩阵进行操作,每次在每一行的行首或行尾取出一个数,第i次取数所得的得分为:第1行所取的数*2^i+第2行所取的数*2^i+...+第n行所取的数*2^i,给定一个矩阵,问最后能得到的最大得分。
做法:由题目可以分析得知每一行是相对独立的,我们可以依次求出每一行可以得到的最大得分,再进行累加,就可以得到整个矩阵能得到的最大得分。设f[i][j]为从行首取i个,从行尾取j个的情况下能得到的最大得分,不难得出状态转移方程:f[i][j]=max(f[i-1][j]+a[h][i],f[i][j-1]+a[h][m-j+1]),其中h为当前正在处理的行数,a[1...n][1...m]存储的是矩阵内的元素。我们以取数次数k来划分阶段,每一阶段中求出f[0][k],...,f[i][k-i],...,f[k][0]。注意,操作过程中的数字可能很大,所以要用高精度数来表示。
以下是本人代码(写得比较烂,将就着看看吧......):
#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;int n,m,a[90][90]={0};int f[90][90][51]={0};int cmp1[51]={0},cmp2[51]={0},cmp3[51]={0},ans[51]={0},pwr[51]={0};int s1[51]={0},s2[51]={0};int main(){ scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); for(int h=1;h<=n;h++) //h:当前要处理的行 { for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) for(int k=1;k<=50;k++) f[i][j][k]=0;for(int i=1;i<=50;i++) pwr[i]=0;pwr[1]=1; //pwr:存储2的次幂for(int k=1;k<=m;k++) //k:表示当前在进行第k次取数{ for(int i=1;i<=50;i++) pwr[i]*=2; for(int i=1;i<=50;i++) if (pwr[i]>=10) {pwr[i+1]+=pwr[i]/10;pwr[i]%=10;} for(int i=0;i<=k;i++) { for(int j=1;j<=50;j++) s1[j]=0;for(int j=1;j<=50;j++) s2[j]=0;for(int j=1;j<=50;j++) cmp1[j]=0;for(int j=1;j<=50;j++) cmp2[j]=0; for(int j=1;j<=50;j++) s1[j]=pwr[j]*a[h][i];for(int j=1;j<=50;j++) if (s1[j]>=10) {s1[j+1]+=s1[j]/10;s1[j]%=10;} //s1=pwr*a[h][i]for(int j=1;j<=50;j++) s2[j]=pwr[j]*a[h][m-(k-i)+1];for(int j=1;j<=50;j++) if (s2[j]>=10) {s2[j+1]+=s2[j]/10;s2[j]%=10;} //s2=pwr*a[h][m-(k-i)+1]if (i>0) //特殊判断,防止访问无效内存{ for(int j=1;j<=50;j++) { cmp1[j]+=f[i-1][k-i][j]+s1[j]; if (cmp1[j]>=10) {cmp1[j+1]+=cmp1[j]/10;cmp1[j]%=10;} } //cmp1=f[i-1][k-i]+a[h][i]*pwr=f[i-1][k-i]+s1}if (k-i>0) //特殊判断,防止访问无效内存{ for(int j=1;j<=50;j++) { cmp2[j]+=f[i][k-i-1][j]+s2[j]; if (cmp2[j]>=10) {cmp2[j+1]+=cmp2[j]/10;cmp2[j]%=10;} } //cmp2=f[i][k-i-1]+a[h][m-(k-i)+1]*pwr=f[i][k-i-1]+s2}bool flag=0;for(int j=50;j>=1;j--) { if (cmp1[j]>cmp2[j]) {flag=1;break;} if (cmp1[j]<cmp2[j]) {flag=0;break;} } //比较两个高精度数的大小if (flag){ for(int j=1;j<=50;j++) f[i][k-i][j]=cmp1[j];}else{ for(int j=1;j<=50;j++) f[i][k-i][j]=cmp2[j];} }}for(int i=1;i<=50;i++) cmp3[i]=0;for(int i=0;i<=m;i++){ bool flag=0; for(int j=50;j>=1;j--) {if (f[i][m-i][j]>cmp3[j]) {flag=1;break;}if (f[i][m-i][j]<cmp3[j]) {flag=0;break;} } if (flag) {for(int j=1;j<=50;j++)cmp3[j]=f[i][m-i][j]; }} //求出该行最大得分for(int i=1;i<=50;i++) ans[i]+=cmp3[i];for(int i=1;i<=50;i++) if (ans[i]>=10) {ans[i+1]+=ans[i]/10;ans[i]%=10;} //将该行最大得分累加进最终解 } bool flag=0; for(int i=50;i>=1;i--) { if (!flag&&ans[i]>0) flag=1;if (flag) printf("%d",ans[i]); } if (!flag) printf("0"); //结果可能为0,特殊判断 return 0;}
0 0
- 【NOIP2007提高组T3】矩阵取数游戏-动态规划+高精度
- noip2007 矩阵取数游戏 (动态规划+高精度)
- NOIP2007 矩阵取数游戏 [dp] [高精度]
- [动态规划+高精度] 矩阵取数游戏
- NOIP2007提高组——矩阵取数游戏(game)
- NOIP2007 提高组 复赛 game 矩阵取数游戏
- NOIP2007提高组 矩阵取数
- ACM 96. [NOIP2007] 矩阵取数游戏(dp+高精度)
- NOIP2007 矩阵取数游戏
- NOIP2007【矩阵取数游戏】
- NOIP2007矩阵取数游戏
- 【NOIP2007】矩阵取数游戏
- NOIP2007 矩阵取数 DP+高精度
- 洛谷 P1005 Tyvj P1054 [NOIP2007 T3] 矩阵取数游戏 [60分 非高精]
- Noip2007矩阵取数游戏题解
- noip2007矩阵取数游戏 2008.11.5
- 【NOIP2007】洛谷1005 矩阵取数游戏
- 洛谷P1005&NOIP2007 矩阵取数游戏
- [网络流]poj3281 Dining
- UVA657The die is cast
- [283] Move Zeroes
- NOIPの模拟_2016_7_20_t2_Graph Coloring
- 函数三要数,函数调用
- 【NOIP2007提高组T3】矩阵取数游戏-动态规划+高精度
- HDU 4597 Play Game[博弈论 负值最大函数 记忆化搜索]
- 使用UUID可以产生一个号称全球唯一的ID
- Checkable API详解
- 一个非计算机专业的安卓工程师成长之路
- Java基础之数组
- 分数加减法
- java基础笔记精简版
- REBOOT流程