金明的预算方案

传送门——金明的预算方案

解题思路

一共有三种可能

一、没有附件

状态转移方程:

dp[j]=max(dp[j],dp[j-c[i]]+v[i]);

就是普通的0-1背包

二、只有一个附件

1.什么都不取
2.取主件
3.取主件和附件

三、有两个附件

1.什么都不取
2.取主件
3.取主件和附件1
4.取主件和附件2
5.取主件,附件1,附件2

代码

#include<iostream>
using namespace std;
int c[100000],p[100000],q[100000],fu[100000],fu1[100000],fu2[100000];
int v[100000];
int main(){
	int n,m;
	int dp[100000];
	cin>>n>>m;
	
	for(int i=1;i<=m;i++){
		cin>>c[i]>>p[i]>>q[i];
		v[i]=c[i]*p[i];
		fu[q[i]]++;
		if(fu1[q[i]]==0){
			fu1[q[i]]=i; 
		}else{
			fu2[q[i]]=i;
		}
		
	}
	for(int i=1;i<=m;i++){
		for(int j=n;j>=0;j--){
			if(q[i]==0){
			if(j>=c[i]){
				if(fu[i]==0){
					dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
				}else if(fu[i]==1){
					dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
					if(j>=c[i]+c[fu1[i]]){
						dp[j]=max(dp[j],dp[j-c[i]-c[fu1[i]]]+v[i]+v[fu1[i]]);
					}
				}else if(fu[i]==2){
					dp[j]=max(dp[j],dp[j-c[i]]+v[i]);
					if(j>=c[i]+c[fu1[i]]){
						dp[j]=max(dp[j],dp[j-c[i]-c[fu1[i]]]+v[i]+v[fu1[i]]);
					}
					if(j>=c[i]+c[fu2[i]]){
						dp[j]=max(dp[j],dp[j-c[i]-c[fu2[i]]]+v[i]+v[fu2[i]]);
					}
					if(j>=c[i]+c[fu1[i]]+c[fu2[i]]){
						dp[j]=max(dp[j],dp[j-c[i]-c[fu1[i]]-c[fu2[i]]]+v[i]+v[fu1[i]]+v[fu2[i]]);
					}
					//dp[j]=max(dp[j],max(dp[j-c[i]]+v[i],max(dp[j-c[i]-c[fu1[i]]+v[i]+v[fu1[i]]],max(dp[j-c[i]-c[fu2[i]]+v[i]+v[fu2[i]]],dp[j-c[i]-c[fu2[i]]-c[fu1[i]]+v[i]+v[fu1[i]]+v[fu2[i]]]))));
				}
			}else{
				dp[j]=dp[j];
			}
		}
		}
	}
/*	for(int i=0;i<=n;i++){
		cout<<i<<": "<<dp[i]<<endl;
	}
	cout<<endl;
*/	cout<<dp[n];
	return 0;
} 

posted on 2019-06-16 19:07  nodeee  阅读(125)  评论(0编辑  收藏  举报