设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()
{
//input
h[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 initialize
memset(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];
//dp
for (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 value
int 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;
}
}
//output
printf("%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;
}