EOJ 1823 数塔II (动态规划入门)
1
/**/
/*
2
EOJ 1823 数塔II
3![]()
4![]()
5
----问题描述:
6![]()
7
有一个由正整数组成的三角形,
8
第一行只有一个数,
9
除了最下行之外每个数的左下方和右下方各有一个数,
10![]()
11
如下图所示:
12![]()
13
1
14
3 2
15
4 10 1
16
4 3 2 20
17![]()
18
从第一行的数开始,除了某一次可以走到下一行的任意位置外,
19
每次都只能左下或右下走一格,
20
直到走到最下行,
21
把沿途经过的数全部加起来,如何走,使得这个和尽量大?
22![]()
23![]()
24
----输入:
25![]()
26
输入数据首先包括一个整数 C,表示测试实例的个数,
27
每个测试实例的第一行是一个整数 N (1 <= N <= 500),表示数塔的高度,
28
接下来用 N 行数字表示数塔,其中第 i 行有 i 个整数,且所有的整数均在区间 [ 0, 99 ] 内。
29![]()
30![]()
31
----输出:
32![]()
33
对于每个测试实例,输出可能得到的最大和。
34![]()
35![]()
36
----样例输入:
37![]()
38
1
39
4
40
1
41
3 2
42
4 10 1
43
4 3 2 20
44![]()
45![]()
46
----样例输出:
47![]()
48
34
49![]()
50![]()
51
*/
52![]()
53![]()
54![]()
/**/
/************************************************************************
55![]()
56
----方案三:
57![]()
58
方案二的空间优化,
59
实际数据范围只有 25 ;
60
使用滚动数组。
61![]()
62
*/
63![]()
/**/
/*
64
#include <stdio.h>
65![]()
66
#define L 25
67![]()
68
int a[L][L], f[L], h[L];
69![]()
70
int main(){
71
int td, n, i, j, ans, tmp;
72
scanf( "%d", &td );
73
while( td-- ){
74
scanf( "%d", &n );
75
for( i=1; i<=n; ++i ){
76
for( j=1; j<=i; ++j ){
77
scanf( "%d", &a[i][j] );
78
}
79
}
80![]()
81
for( j=1; j<=n; ++j ){
82
f[j] = h[j] = a[n][j];
83
}
84
for( i=n-1; i>0; --i ){
85
tmp = h[i+1];
86
for( j=1; j<=i; ++j ){
87
tmp = ( tmp < h[j] ? h[j] : tmp );
88
}
89
for( j=1; j<=i; ++j ){
90
h[j] = a[i][j] + ( h[j] > h[j+1] ? h[j] : h[j+1] );
91
f[j] = a[i][j] + ( f[j] > f[j+1] ? f[j] : f[j+1] );
92
f[j] = ( (tmp+a[i][j]) > f[j] ? (tmp+a[i][j]) : f[j] );
93
}
94
}
95![]()
96
ans = f[1];
97
printf( "%d\n", ans );
98
}
99
return 0;
100
}
101
*/
102![]()
103![]()
104![]()
/**/
/************************************************************************
105![]()
106
----方案二
107![]()
108
令 a[i][j] 表示第 i 行第 j 个数字,(1 <= j <= i <= n);
109
令 h[i][j] 表示从 a[i][j] 开始走到最后一行所能得到的最大和,其中每次都只能左下或右下走一格;
110
令 f[i][j] 表示从 a[i][j] 开始走到最后一行所能得到的最大和,其中某一次走到了下一行的任意位置;
111![]()
112
则
113
h[i][j] = a[i][j] + max( h[i+1][j], h[i+1][j+1] )
114
f[i][j] = a[i][j] + max( f[i+1][j], f[i+1][j+1], h[i+1][k] ) 其中 1 <= k <= i+1
115![]()
116
结果为 f[1][1]。
117![]()
118
*/
119![]()
/**/
/*
120
#include <stdio.h>
121![]()
122
#define L 503
123![]()
124
int a[L][L], f[L][L], h[L][L];
125![]()
126
int main(){
127
int td, n, i, j, ans, tmp;
128
scanf( "%d", &td );
129
while( td-- ){
130
scanf( "%d", &n );
131
for( i=1; i<=n; ++i ){
132
for( j=1; j<=i; ++j ){
133
scanf( "%d", &a[i][j] );
134
}
135
}
136![]()
137
for( j=1; j<=n; ++j ){
138
f[n][j] = h[n][j] = a[n][j];
139
}
140
for( i=n-1; i>0; --i ){
141
tmp = h[i+1][i+1];
142
for( j=1; j<=i; ++j ){
143
tmp = ( tmp < h[i+1][j] ? h[i+1][j] : tmp );
144
}
145
for( j=1; j<=i; ++j ){
146
h[i][j] = a[i][j] + ( h[i+1][j] > h[i+1][j+1] ? h[i+1][j] : h[i+1][j+1] );
147
f[i][j] = a[i][j] + ( f[i+1][j] > f[i+1][j+1] ? f[i+1][j] : f[i+1][j+1] );
148
f[i][j] = ( (tmp+a[i][j]) > f[i][j] ? (tmp+a[i][j]) : f[i][j] );
149
}
150
}
151![]()
152
ans = f[1][1];
153
printf( "%d\n", ans );
154
}
155
return 0;
156
}
157
*/
158![]()
159![]()
160![]()
/**/
/************************************************************************
161![]()
162
----方案一
163![]()
164
令 a[i][j] 表示第 i 行第 j 个数字,(1 <= j <= i <= n);
165
令 h[i][j] 表示从第一行的数开始走到 a[i][j] 所能得到的最大和,其中每次都只能左下或右下走一格;
166
令 f[i][j] 表示从 a[i][j] 开始走到最后一行所能得到的最大和,每次都只能左下或右下走一格;
167![]()
168
则
169
h[i][j] = a[i][j] + max( h[i-1][j-1], h[i-1][j] )
170
f[i][j] = a[i][j] + max( f[i+1][j], f[i+1][j+1] )
171![]()
172
结果为 max( h[i][j], f[i+1][k] ) 。
173![]()
174
*/
175![]()
/**/
/*
176
#include <stdio.h>
177![]()
178
#define L 503
179![]()
180
int a[L][L], f[L][L], h[L][L];
181![]()
182
int main(){
183
int td, n, i, j, k, ans;
184
scanf( "%d", &td );
185
while( td-- ){
186
scanf( "%d", &n );
187
for( i=1; i<=n; ++i ){
188
for( j=1; j<=i; ++j ){
189
scanf( "%d", &a[i][j] );
190
}
191
}
192![]()
193
for( j=1; j<=n; ++j ){
194
f[n][j] = a[n][j];
195
}
196
for( i=n-1; i>0; --i ){
197
for( j=1; j<=i; ++j ){
198
f[i][j] = a[i][j] + ( f[i+1][j] > f[i+1][j+1] ? f[i+1][j] : f[i+1][j+1] );
199
}
200
}
201![]()
202
h[1][1] = a[1][1];
203
for( i=2; i<=n; ++i ){
204
h[i][1] = a[i][1] + h[i-1][1];
205
h[i][i] = a[i][i] + h[i-1][i-1];
206
for( j=2; j<i; ++j ){
207
h[i][j] = a[i][j] + ( h[i-1][j-1] > h[i-1][j] ? h[i-1][j-1] : h[i-1][j] );
208
}
209
}
210![]()
211
ans = f[1][1];
212
for( i=1; i<n; ++i ){
213
for( j=1; j<=i; ++j ){
214
for( k=i+1; k>0; --k ){
215
if( h[i][j] + f[i+1][k] > ans ){
216
ans = h[i][j] + f[i+1][k];
217
}
218
}
219
}
220
}
221![]()
222
printf( "%d\n", ans );
223
}
224
return 0;
225
}
226
*/
227
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227