链接:点击打开链接
题意:给出n个物品,和背包容量m,给出每个物品的价值,重量,和取得这个物品获得的额外的背包容量,可以最多选择两个物品获得额外的背包容量,问最后的最大价值
代码:
#include <queue>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
long long p,w,d;
friend bool operator<(node a,node b){
return a.d>b.d;
}
}s[10005];
long long dp[10005][1005][3];
int main(){ //dp[i][j][k]表示到第i个,背包容量是j,用了
long long n,m,i,j,k,ans; //k次机会
while(scanf("%I64d%I64d",&n,&m)!=EOF){
for(i=1;i<=n;i++)
scanf("%I64d%I64d%I64d",&s[i].p,&s[i].w,&s[i].d);
sort(s+1,s+n+1); //设计出状态后其实转移方程很好推
memset(dp,-1,sizeof(dp)); //关键在于需要先排序在进行dp,就是让上一行
dp[0][m][0]=0; //可行的状态尽可能多,才能满足这行状态尽可
for(i=1;i<=n;i++){ //能多
for(j=0;j<=m+200;j++)
for(k=0;k<=2;k++)
dp[i][j][k]=dp[i-1][j][k];
for(j=0;j<=m+200;j++){
for(k=0;k<=2;k++){
if(dp[i-1][j][k]!=-1&&j>=s[i].w)
dp[i][j-s[i].w][k]=max(dp[i][j-s[i].w][k],dp[i-1][j][k]+s[i].p);
if(dp[i-1][j-s[i].d+s[i].w][k-1]!=-1&&k>=1&&j-s[i].d+s[i].w>=0)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-s[i].d+s[i].w][k-1]+s[i].p);
}
}
}
ans=0;
for(i=0;i<=m+200;i++){
for(j=0;j<=2;j++)
if(dp[n][i][j]!=-1)
ans=max(ans,dp[n][i][j]);
}
printf("%I64d\n",ans);
}
return 0;
}