搭建双塔,貌似是非常有名的一道题,OI的 dp[i][j]表示使用前i个水晶块的时候,两座塔的误差为j时两座塔共有的最高高度,对于第i个木块,有三种情况,第一种不放,第二种放在其中挨塔上,此时更新误差值以及共有的最高高度值,第三种情况放在高塔上,此时仅仅更新误差值。 view code #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; #define MAX 2500 int n, a[150], sum[150], dp[150][2010], i, j, k; int max(int c, int a, int b) { int x; if (a > b) x = a; else x = b; if (x > c) return x; else return c; } int main() { scanf("%d", &n);; for (i = 1; i <= n; i++) { scanf("%d", &a[i]); sum[i] = sum[i - 1] + a[i]; } for (i = 0; i < 150; i++) for (j = 0; j < 2010; j++) dp[i][j] = -10000; dp[0][0] = 0; for (i = 1; i <= n; i++) for (j = sum[i]; j >= 0; j--) { if (a[i] >= j) dp[i][j] = max(dp[i - 1][j], dp[i - 1][a[i] - j] + j, dp[i - 1][j + a[i]]); else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - a[i]] + a[i], dp[i - 1][j + a[i]]); } k = -1; for (i = 1; i <= n; i++) if (k < dp[i][0]) k = dp[i][0]; if (k > 0) printf("%d\n", k); else printf("Impossible\n"); return 0; }
|