题目大意
略
解题思路
最终的结果可以用数字,减号与括号表示,如果把所有的括号去掉,就得到了一个由数字,加法与减法组成的式子,可以想到,对于每一个数字,都有加上它或者减去它两种情况,很明显可以用01背包来解决。需要注意的一点是,第一个数字前头没有符号,而第二个数字肯定是被减的。
那么怎么还原操作顺序呢?一个数字前面是加号,那他前面肯定存在一个数字前面是减号,比如-a+b+c+d这样,可以转化为-(((a-b)-c)-d),那么我们可以先执行a-b, a-c, a-d,最后再-a就可以了,所以对于每一个前面是加号的数字,我们可以找一个前面里它最近的前面是减号的数字作为答案。可以发现如果我们正着做的话,在删除的过程中由于前面的数字少了,当前的数字的序号会发生改变,如果我们倒着来做的话,即使删除了后面的数字前面的序号也不会改变,写起来也简单。最后剩下一些前面是减号的数字,用第一个数字来减它们就行了。
代码
#include<bits/stdc++.h>
#define endl '
'
#define x first
#define y second
#define clr(arr,a) memset(arr, a, sizeof(arr))
#define IOS ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef pair<int, int> Pll;
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int maxn = 1e2+10;
const int maxm = 2e4+10;
int n, t, arr[maxn], dp[maxn][maxm], op[maxn];
int main() {
cin >> n >> t;
for (int i = 1; i<=n; ++i) cin >> arr[i];
dp[2][10005+arr[1]-arr[2]] = -1;
for (int i = 3; i<=n; ++i)
for (int j = maxm; j>=0; --j)
if (dp[i-1][j]) {
if (j+arr[i]<maxm) dp[i][j+arr[i]] = 1;
if (j-arr[i]>=0) dp[i][j-arr[i]] = -1;
}
int now = 10005+t;
for (int i = n; i>=2; --i) {
if (dp[i][now]>0) now -= arr[i], op[i] = 1;
else now += arr[i], op[i] = -1;
}
vector<int> ans;
int p;
for (int i = 2; i<=n; ++i) {
if (op[i]<0) p = i;
else ans.push_back(p);
}
reverse(ans.begin(), ans.end());
for (int i = 2; i<=n; ++i)
if (op[i]<0) ans.push_back(1);
for (auto v : ans) cout << v << endl;
return 0;
}