洛谷1064 金明的预算方案 01背包变种
题目链接:https://www.luogu.com.cn/problem/P1064
就是一个01背包的变种问题,只是选择的可能情况不同。对于01背包,对第i个物品,选择的情况有两种:选择或者不选择,而本问题中选择的情况有五种:对于一个主件来说,可以不选择,可以只选择主件,可以选择主件+第一个附件(如果有的话),还可以选择主件+第二个附件(如果有的话),还可以选择主件+第一个附件+第二个附件(如果有的话)。唯一的注意点就是编号是连续的,附件的编号不起作用,所属主件的编号是输入中有序的编号,循环过程需要判断是否是主件,因为主件必须要有。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define dbg(args) cout<<#args<<":"<<args<<endl; 17 #define inf 0x3f3f3f3f 18 #define maxn 100005 19 int n,m,t; 20 int v[maxn],w[maxn],cnt[maxn],ww[maxn][5],vv[maxn][5],dp[maxn]; 21 //cnt表示第k个主件的附件数量 ,ww:附件的权重 vv:附件的价值 22 int main() 23 { 24 //freopen("P1064_5.txt","r",stdin); 25 //freopen("output.txt","w",stdout); 26 std::ios::sync_with_stdio(false); 27 scan(m); 28 scan(n); 29 int q,x,y; 30 f(i,1,n) 31 { 32 scan(x); 33 scan(y); 34 scan(q); 35 if(q) 36 { 37 cnt[q]++;//表示第i编号的是附件,q的第cnt个附件,附件最多是两个 38 ww[q][cnt[q]]=x*y; 39 vv[q][cnt[q]]=x; 40 } 41 else 42 { 43 w[i]=x*y; 44 v[i]=x; 45 } 46 47 } 48 f(i,1,n) 49 for(int j=m;j>=v[i]&&v[i]!=0;j--)//v[i]不等于零表示该编号的主件存在 50 { 51 dp[j]=max(dp[j],dp[j-v[i]]+w[i]); 52 if(!cnt[i])continue;//没有附件 53 if(cnt[i]>=1) 54 { 55 if(j-v[i]-vv[i][1]>=0) 56 dp[j]=max(dp[j],dp[j-v[i]-vv[i][1]]+w[i]+ww[i][1]); 57 } 58 if(cnt[i]>=2) 59 { 60 if(j-v[i]-vv[i][2]>=0) 61 { 62 dp[j]=max(dp[j],dp[j-v[i]-vv[i][2]]+w[i]+ww[i][2]); 63 } 64 if(j-v[i]-vv[i][1]-vv[i][2]>=0) 65 { 66 dp[j]=max(dp[j],dp[j-v[i]-vv[i][1]-vv[i][2]]+w[i]+ww[i][1]+ww[i][2]); 67 } 68 69 } 70 } 71 pf("%d",dp[m]); 72 }
每一个不曾起舞的日子,都是对生命的辜负。