题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1126
题解:一道基础的dp就是简单的递推可以设dp[height_left][height_right],但是这样显然回boom内存,所以不妨直接考虑两座塔之间的差于是便有了dp[i][j]表示考虑到第几个时两座塔差值是多少,然后就是递推了,要么加积木嫁到高的塔上要么就嫁到底的塔上要么都不嫁,这样递推方程就好写了。如果这样还是boom内存的话可以考虑用滚动优化i这一维。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int M = 5e5 + 10; int a[55] , dp[2][M]; int main() { int t; scanf("%d" , &t); int Case = 0; while(t--) { int n; scanf("%d" , &n); int sum = 0; for(int i = 1 ; i <= n ; i++) { scanf("%d" , &a[i]); sum += a[i]; } sum /= 2; memset(dp , -1 , sizeof(dp)); dp[0][0] = 0; int flag = 0; for(int i = 1 ; i <= n ; i++) { flag = i % 2; for(int j = 0 ; j <= sum ; j++) { dp[flag][j] = max(dp[flag ^ 1][j] , dp[flag][j]); if(dp[flag ^ 1][j] != -1) { dp[flag][j + a[i]] = max(dp[flag][j + a[i]] , dp[flag ^ 1][j] + a[i]); if(j >= a[i]) { dp[flag][j - a[i]] = max(dp[flag][j - a[i]] , dp[flag ^ 1][j]); } else { dp[flag][a[i] - j] = max(dp[flag][a[i] - j] , dp[flag ^ 1][j] - j + a[i]); } } } } if(dp[flag][0] > 0) { printf("Case %d: %d " , ++Case , dp[flag][0]); } else { printf("Case %d: impossible " , ++Case); } } return 0; }