sgu482 Impudent Thief (动态规划)

来源:互联网 发布:c语言且 编辑:程序博客网 时间:2024/05/22 16:04

设dp[i][j]为最后一个放i,周长为j所拿走的木板总高度

dC(i, j)表示i与j放在一起,周长的改变量

这样dp方程如下

dp[k][j + dC(i, k)] = max{dp[i][j] - h[k]} , k > i

时间复杂度为O(n^2*C),即O(n^3*h)

#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int MAXN = 55;const int MAXC = 5210;const int INF = 0x3f3f3f3f;int h[MAXN], sum[MAXN], dp[MAXN][MAXC], fat[MAXN][MAXC];bool vis[MAXN];vector<int> ansV;inline int dC(int u, int v){int res = 2;if (h[v] > h[u]) res += 2 * (h[v] - h[u]);return res;} int main(){//inputh[0] = sum[0] = 0;int sumC = 0;ansV.clear();memset(vis, false, sizeof(vis));int n; scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d", &h[i]);sum[i] = sum[i-1] + h[i];sumC += dC(i - 1, i);}int mid = (sumC + 1) / 2;//dp initializememset(dp, 0, sizeof(dp));memset(fat, 0, sizeof(fat));for (int i = 1; i <= n; i++) dp[i][2*h[i]+2] = sum[n] - h[i];//dpfor (int i = 1; i <= n; i++)for (int j = 0; j < MAXC; j++){if (dp[i][j]){for (int k = i + 1; k <= n; k++){if (dp[i][j] - h[k] > dp[k][j + dC(i, k)]){dp[k][j + dC(i, k)] = dp[i][j] - h[k];fat[k][j + dC(i, k)] = i;}}}}//get the biggest valueint ans = 0, ansi = 0, ansj = 0;for (int i = 1; i <= n; i++)for (int j = mid; j < MAXC; j++){if (dp[i][j] > ans){ans = dp[i][j];ansi = i;ansj = j;}}//outputprintf("%d\n", ans);if (ans == 0){printf("0\n");return 0;}int cnt = 0;while (ansi){vis[ansi] = true; cnt++;int ti = fat[ansi][ansj];int tj = ansj - dC(ti, ansi);ansi = ti;ansj = tj;}printf("%d\n", n - cnt);bool flag = false;for (int i = 1; i <= n; i++){if (!vis[i]){flag ? printf(" ") : flag = true;printf("%d", i);}}printf("\n");return 0;}


0 0