矩阵选数——高精度

难点:转移方程的确定;高精度;

首先本题可以逐行考虑,然后把每行的最大值相加,就是最终结果。而每一行的转移方程为:

f[i][j]=2*max{f[i+1][j]+a[i],f[i][j-1]+a[j]}

结合循环分析转移方程:

  for(k=1;k<=m;k++)
  for(i=1;i<=m-k+1;i++)

循环是逐个增加考虑元素的个数的。k代表元素个数,i代表起始元素,j=i+k-1,是末元素的

下标。“f[i+1][j]+a[i],f[i][j-1]+a[j]”代表取头或取尾元素,选其中最大的,然后乘以2.

之所以乘以2,代表i或者j元素是最先取的,故乘以2.而既然i或j是最先取的,那么前面状态的元

素当然要向后推一次取,所以乘以2.那么f[i][j]就代表从i到j的元素,第一个取取i或j

得到的最大值

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < string .h >
4 int f[ 81 ][ 81 ][ 80 ],sum[ 80 ];
5 int a[ 81 ][ 81 ],s2[ 80 ];
6 int n,m,sf[ 81 ][ 81 ],sa[ 81 ];
7 char a1[ 81 ];
8 FILE * in , * out ;
9
10 int plus( int * p, int * q, int l1, int l2, int * k)
11 {
12 int i,c,s = 0 ,l;
13 if (l1 > l2)l = l1;
14 else l = l2;
15 for (i = 0 ;i < l;i ++ )
16 {
17 s += p[i] + q[i];
18 c = s % 10 ;
19 s = s / 10 ;
20 k[i] = c;
21 }
22
23 while (s != 0 )
24 {
25 c = s % 10 ;
26 s = s / 10 ;
27 k[i ++ ] = c;
28 }
29 return i;
30 }
31
32 int max( int * p, int * q, int l1, int l2)
33 {
34 if (l1 > l2) return 1 ;
35 else
36 if (l1 < l2) return 0 ;
37 else
38 {
39 int i;
40 for (i = l2 - 1 ;i >= 0 ;i -- )
41 if (p[i] > q[i]) return 1 ;
42 else
43 if (q[i] > p[i]) return 0 ;
44 return 0 ;
45 }
46 }
47
48
49 int main(){
50 in = fopen( " game7.in " , " r " );
51 out = fopen( " game.ans " , " w " );
52 fscanf( in , " %d %d\n " , & n, & m);
53 int i,j,j1,k,w,i1,ls = 0 ,lss;
54 int le1,le2;
55 int x;
56 memset(sum, 0 , sizeof (sum));
57
58 for (i1 = 1 ;i1 <= n;i1 ++ )
59 {
60 memset(a1, 0 , sizeof (a1));
61 memset(f, 0 , sizeof (f));
62 memset(sf, 0 , sizeof (sf));
63 memset(a, 0 , sizeof (a));
64 for (j1 = 1 ;j1 <= m;j1 ++ )
65 {
66 fscanf( in , " %s " ,a1);
67 lss = strlen(a1);
68 sa[j1] = lss;
69 for (j = lss - 1 ;j >= 0 ;j -- )
70 a[j1][lss - j - 1 ] = a1[j] - ' 0 ' ;
71 }
72
73 for (k = 1 ;k <= m;k ++ )
74 for (i = 1 ;i <= m - k + 1 ;i ++ )
75 {
76 memset(s2, 0 , sizeof (s2));
77 j = k + i - 1 ;
78
79 sf[i][j] = plus(f[i + 1 ][j],a[i],sf[i + 1 ][j],sa[i],f[i][j]);
80 sf[i][j] = plus(f[i][j],f[i][j],sf[i][j],sf[i][j],f[i][j]);
81 le2 = plus(f[i][j - 1 ],a[j],sf[i][j - 1 ],sa[j],s2);
82 le2 = plus(s2,s2,le2,le2,s2);//加两次,相当于乘以2
83 if (max(s2,f[i][j],le2,sf[i][j]))
84 {
85 for (w = 0 ;w < le2;w ++ )
86 f[i][j][w] = s2[w];
87 sf[i][j] = le2;
88 }
89 }
90 ls = plus(sum,f[ 1 ][m],ls,sf[ 1 ][m],sum);
91 }
92
93 for (i = ls - 1 ;i >= 0 ;i -- )
94 fprintf( out , " %d " ,sum[i]);
95 fprintf( out , " \n " );
96 fclose( in ); fclose( out );
97 return 0 ;
98 }
99

 

 

 

转载于:https://www.cnblogs.com/aiyite826/archive/2010/08/02/1790510.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值