当前位置: 代码迷 >> 综合 >> poj - 1722 - SUBTRACT(dp)
  详细解决方案

poj - 1722 - SUBTRACT(dp)

热度:60   发布时间:2024-01-10 12:51:06.0

题意:一个长为 N (1 <= N <= 100)的序列(1 <= ai <= 100),一次操作为删除 a[i] 和 a[i + 1],然后将它们的差(a[i] - a[i + 1])放入该位置,问 N - 1 次操作后得到 T (-10000 <= T <= 10000)的操作顺序是什么?

题目链接:http://poj.org/problem?id=1722

——>>每次操作相当于给 a[i] 和 a[i + 1] 加括号做减法,那么把所有的括号去掉后就是对序列第一次做减法,后面或加法或减法。。

状态:dp[i][j] 表示前 i 个数的运算结果为 j 时最后一次的运算符号。。("+" 或 "-")

状态转移方程:

dp[i + 1][j - a[i + 1]] = '-';

dp[i + 1][j + a[i + 1]] = '+';

#include <cstdio>
#include <cstring>const int MAXN = 100 + 10;
const int MAXT = 20000 + 10;
const int MID = 10000;int N, T;
int a[MAXN];
char dp[MAXN][MAXT];
char op[MAXN];void Read()
{for (int i = 1; i <= N; ++i){scanf("%d", a + i);}
}void Dp()
{if (N == 1) return;memset(dp, 0, sizeof(dp));dp[2][a[1] - a[2] + MID] = '-';for (int i = 2; i < N; ++i){for (int j = 0; j < (MID << 1); ++j){if (dp[i][j] != 0){dp[i + 1][j - a[i + 1]] = '-';dp[i + 1][j + a[i + 1]] = '+';}}}
}void GetPath()
{int t = T + MID;for (int i = N; i >= 2; --i){op[i] = dp[i][t];if (op[i] == '+'){t -= a[i];}else{t += a[i];}}
}void Output()
{int done = 0;for (int i = 2; i <= N; ++i){if (op[i] == '+'){printf("%d\n", i - 1 - done);++done;}}for (int i = 2; i <= N; ++i){if (op[i] == '-'){puts("1");}}
}int main()
{while (scanf("%d%d", &N, &T) == 2){Read();Dp();GetPath();Output();}return 0;
}