洛谷题号:P1651

出处: 全国信息学分区联赛模拟试题(6)T1

主要算法:动态规划

难度:4.5

https://www.luogu.org/problemnew/show/P1651

思路分析:

       思路特别有意思,f[i][j]表示使用前i块木块,高度差为j时较高的塔的最大高度。

       这道题有点考察dp的基本功,f[i][j]能由那些状态转移而来?

       考虑每一块木块,可以选择不用,放在左边,放在右边,三种。

       如果不用,那很简单,直接由f[i-1][j]转移而来。

       如果放在较高的那一堆,那么高度差反而会变大。当前差值为j,那么是由j-a[i]转移过来的,所以由f[i-1][j-a[i]]转移而来,并且要加上a[i]。前提是j>=a[i]

       如果放在较低的那一堆,那么需要分类讨论:放完之后低的那一堆反而会比原先高的那堆高,还是仍然低于高的那一堆?对于第一种情况,需要满足的是j<=a[i],因为原先要比高的那堆低,所以是由f[i-1][a[i]-j]转移而来的,并且还需要加上新增的高度j。前提是a[i]>=j。对于后一种情况,是由a[i]+j转移过来的,同时最大值不变。

       就这样,答案就是f[n][0],当然要特判一下如果f[n][0]==0,那么输出-1.

代码注意点:

F数组先置成-∞,因为有的高度差是根本达不到的,这是如果是0转移就会出现错误。

 1 /*By QiXingzhi*/
 2 #include <cstdio>
 3 #include <cstring>
 4 #define  N  (53)
 5 #define  INF   (0x3f3f3f3f)
 6 #define  Max(a,b)  (((a)>(b))?(a):(b))
 7 #define  Min(a,b)  (((a)<(b))?(a):(b))
 8 #define  read(x)  x=__get_integer__()
 9 typedef long long ll;
10 using namespace std;
11 inline int __get_integer__(){
12     int x = 0; int w = 1; register char c = getchar();
13     while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
14     if(c == '-') w = -1, c = getchar();
15     while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
16     return x * w;
17 }
18 #define __file(x)  freopen(x".in","r",stdin);
19 #define __file_inout(x)  freopen(x".in","r",stdin),freopen(x".out","w",stdout);
20 int n,t,ans;
21 int a[N],f[N][500010];
22 int main(){
23 //    __file();
24     read(n);
25     for(int i = 1; i <= n; ++i){
26         read(a[i]);
27         t += a[i];
28     }
29     memset(f,-0x3f,sizeof(f));
30     f[0][0] = 0;
31     for(int i = 1; i <= n; ++i){
32         for(int j = 0; j <= t; ++j){
33             f[i][j] = Max(f[i][j], f[i-1][j]);
34             f[i][j] = Max(f[i][j], f[i-1][j+a[i]]);
35             if(j >= a[i]){
36                 f[i][j] = Max(f[i][j], f[i-1][j-a[i]] + a[i]);
37             }
38             if(j <= a[i]){
39                 f[i][j] = Max(f[i][j], f[i-1][a[i]-j] + j);
40             }
41         }
42     }
43     if(f[n][0] == 0) printf("-1");
44     else printf("%d",f[n][0]);
45     return 0;
46 }

2018-06-10 11:32:49

猜你喜欢

转载自www.cnblogs.com/qixingzhi/p/9194680.html