https://vijos.org/p/1071
01背包+输出最优解,在丢失牌的重量中进行01背包
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ms(i,j) memset(i, j, sizeof(i));
using namespace std;
int w[105];
int f[100005];
int g[100005];
int vi[105];
int TotalW, n;
void pri(int t)
{
if (t==0) return ;
for (int i=n;i>0;i--)
{
if (!vi[i]&&t-w[i]==g[t])
{
vi[i] = true;
pri(g[t]);
printf("%d ", i);
}
}
}
int main()
{
scanf("%d%d", &TotalW, &n);
TotalW = -TotalW;
for (int i=1;i<=n;i++)
{
scanf("%d", &w[i]);
TotalW += w[i];
}
ms(f,0); ms(g,0); f[0] = 1;
for (int i=1;i<=n;i++)
for (int j=TotalW;j>=w[i];j--)
{
f[j] += f[j-w[i]];
if(f[j-w[i]] > 0)
g[j] = j-w[i];
}
ms(vi,0);
if (f[TotalW]>1) printf("-1\n");
else if (f[TotalW]==0) printf("0\n");
else pri(TotalW);
return 0;
}