题意:有N组成员,每组成员有四个人,分别代表四个学家的知识点,然后还有一个数代表选择这组能获得的知识,但是这个四个学家的知识点各个之和不得超过他们的限制条件,要我们找到最大价值的所选择的组别。
思路:正常的01背包,但是要输出路径我们就用状态压缩来存路径即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=40;
int dp[N][N][N][N];
long long path[N][N][N][N];
struct node
{
int p,a,c,m,w;
}b[N];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
memset(path,0,sizeof(path));
for(int i=0;i<n;i++)
{
scanf("%d%d%d%d%d",&b[i].p,&b[i].a,&b[i].c,&b[i].m,&b[i].w);
}
int p,a,c,m;
scanf("%d%d%d%d",&p,&a,&c,&m);
for(int i=0;i<n;i++)
{
for(int j=p;j>=b[i].p;j--)
{
for(int x=a;x>=b[i].a;x--)
{
for(int y=c;y>=b[i].c;y--)
{
for(int z=m;z>=b[i].m;z--)
{
if(dp[j][x][y][z]<dp[j-b[i].p][x-b[i].a][y-b[i].c][z-b[i].m]+b[i].w)
{
dp[j][x][y][z]=dp[j-b[i].p][x-b[i].a][y-b[i].c][z-b[i].m]+b[i].w;
path[j][x][y][z]=path[j-b[i].p][x-b[i].a][y-b[i].c][z-b[i].m]|(1LL<<i);
}
}
}
}
}
}
int f=0;
int ans[N];
for(int i=0;i<n;i++)
{
if(path[p][a][c][m]&(1LL<<i))
{
ans[f++]=i;
}
}
printf("%d\n",f);
for(int i=0;i<f;i++)
{
if(i)printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}