思路:背包+逆推。
很明显可以发现:
所以我们定义背包数组
这道题的难点是逆推操作位置。
以下正负数都是指添了号之后的数
可以发现,第3个数以后的一段连续的正数前面一定是一个负数。
形如:(字母均表示正数)
则有:(负负得正)
所以,我们可以先把连续正数及其前面的那一个数合并起来,最后减去剩余的数即可。
具体的,顺序扫描数组,
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=110,X=10000;
int n,m,s;
char f[N][2*X+5],o[N],a[N];
int main() {
scanf("%d %d",&n,&m); m+=X;
for(int i=1,x;i<=n;i++)scanf("%d",&x),a[i]=x;
f[2][a[1]-a[2]+X]=-1;s=abs(a[1]-a[2]);
for(int i=3;i<=n;s+=a[i++])
for(int j=-s;j<=s;j++)
if(f[i-1][j+X]) {
f[i][j+a[i]+X]=1;
f[i][j-a[i]+X]=-1;
}
for(int i=n;i>1;i--)
m-=(o[i]=f[i][m])*a[i];
s=0;
for(int i=3;i<=n;i++)
if(o[i]==1)
printf("%d\n",i-++s);
while(++s<n)puts("1");
return 0;
}