题意:给定花费上限 ,你有 件物品,有m 件装饰品,每件物品和每件装饰品都有两个值攻击力 和花费 。一个物品最多被一个装饰品所装饰,每个装饰品不能独立存在,问在不超过花费上限的前提下,攻击力最大能到达多少.
购买限制:物品最多只能买五个.并且同一种商品不能重复购买.
分析:每种商品只能选购一次,那么就是01背包问题,状态的值就是当前ATK的最大值.
- 根据数据范围开状态,我们可以让花费作为状态的第一维,题目限制买的物品数量不超过5个,购买物品的数量作为状态的第二维,并且装饰品与物品数量相关,购买装饰品的数量作为第三维。
- 因为购买装饰品与购买物品唯一相关联的是数量,那么我们可以分两次背包,第一次背物品,第二次根据物品数量背装饰品。
- 然后重新跑遍所有状态取最大值.
#include<bits/stdc++.h> using namespace std; const int maxn=10005; int dp[140][6][6]; int main() { int n,m,d; scanf("%d%d%d",&n,&m,&d); memset(dp,-0x3f,sizeof(dp)); dp[0][0][0]=0; for( int i=1;i<=n;i++ ) { int x,y; scanf("%d%d",&x,&y); for( int j=d;j>=y;j-- ) { for( int k=1;k<=5;k++ ) dp[j][k][0]=max(dp[j][k][0],dp[j-y][k-1][0]+x); } } for( int i=1;i<=m;i++ ) { int x,y; scanf("%d%d",&x,&y); for( int j=d;j>=y;j-- ) { for( int k=1;k<=5;k++ ) { for( int l=1;l<=k;l++ ) dp[j][k][l]=max(dp[j][k][l],dp[j-y][k][l-1]+x); } } } int ans=-1; for( int i=0;i<=d;i++ ) for( int j=0;j<=5;j++ ) for( int k=0;k<=5;k++ ) ans=max(ans,dp[i][j][k]); printf("%d\n",ans); }