题解 | #购物单#

购物单

http://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4

菜人写这个题真的经历了太多
首先要把一维数组变成[主件][附件]的二维数组(m*3)
初始化的时候只要有钱就买附件
dp数组更新时有钱可以买附件也可以不买,用来买别的,找dp最大的情况,
可以先买主件,有钱买附件时再和这个值作比较,找出最优解

/*HJ16购物单
每件物品只买一次:0-1背包问题
先买主件才能买附件
花费不超过N元,求最大满意度 
*/
#include <iostream>
#include <vector>
using namespace std;
int main()
{
	int N,m;//总钱数and可购买物品的个数
	cin>>N>>m;
	int temp=0; 
	vector<vector<int> >dp(60,vector<int>(32000,0));
	vector<vector<int> >price(60,vector<int>(3));
	vector<vector<int> >impo(60,vector<int>(3));
	vector<int>cla(60);
	vector<vector<int> >sati(60,vector<int>(3));
	for(int i=0;i<m;i++)
	{
		cin>>price[i][0]>>impo[i][0]>>cla[i];
	}
//	cout<<"satip:"<<endl;
	for(int i=0;i<m;i++)//计算满意度 
	{
		sati[i][0]=impo[i][0]*price[i][0];
//		cout<<sati[i][0]<<endl;
	}
	for(int i=0;i<m;i++)//price二维数组 
	{
		if(cla[i]!=0&&price[cla[i]-1][1]==0) price[cla[i]-1][1]=price[i][0];
		else if(cla[i]!=0&&price[cla[i]-1][1]!=0) price[cla[i]-1][2]=price[i][0];		
	}	
	for(int i=0;i<m;i++)//sati二维数组 
	{
		if(cla[i]!=0&&sati[cla[i]-1][1]==0) sati[cla[i]-1][1]=sati[i][0];
		else if(cla[i]!=0&&sati[cla[i]-1][1]!=0) sati[cla[i]-1][2]=sati[i][0];
	}
	for(int i=0;i<m;i++)//price/sati二维数组修改 ,记得cla一起删啊啊啊啊啊 
	{
		if(cla[i]!=0)
		{
			price.erase(price.begin()+i);
			sati.erase(sati.begin()+i);
			cla.erase(cla.begin()+i);
			i--;
			m--; 
		}		
	}
	for(int i=0;i<m;i++)//便宜的附件放前面 
	{
		int t=0;
		if(price[i][1]>price[i][2]) 
		{
			t=price[i][1];price[i][1]=price[i][2];price[i][2]=t;
			t=sati[i][1];sati[i][1]=sati[i][2];sati[i][2]=t;
		}		
	}	
//	cout<<"price:"<<endl;
//	for(int i=0;i<m;i++)
//	{
//		for(int j=0;j<3;j++)
//		cout<<price[i][j]<<" ";
//		cout<<endl;
//	}
//	cout<<"sati:"<<endl;
//	for(int i=0;i<m;i++)
//	{
//		for(int j=0;j<3;j++)
//		cout<<sati[i][j]<<" ";
//		cout<<endl;
//	}
	/*dp数组初始化*/
	for(int i=0;i<m;i++)//没钱啥满意度也没有 
	{
		dp[i][0]=0;
	} 
	for(int j=1;j<=N;j++)//dp数组第一行初始化 
	{
		if(j>=price[0][0])//够买主件 
		dp[0][j]=sati[0][0];
		if(j>=(price[0][0]+price[0][1])) //够买主件和附件1 
		dp[0][j]=sati[0][0]+sati[0][1];
		if(j>=(price[0][0]+price[0][2]))//够买主件和附件2 或 主件和附件1
		dp[0][j]=sati[0][0]+max(sati[0][1],sati[0][2]);
		if(j>=(price[0][0]+price[0][1]+price[0][2]))//够买主件、附件1、附件2 
		dp[0][j]=sati[0][0]+sati[0][1]+sati[0][2];
	}
	/*dp数组更新*/
	for(int i=1;i<m;i++)
	for(int j=1;j<=N;j++)
	{
		dp[i][j]=dp[i-1][j];
		if(j>=price[i][0])//买得起主件 
		dp[i][j]=max(dp[i-1][j],dp[i-1][j-price[i][0]]+sati[i][0]);
		if(price[i][1]!=0||price[i][2]!=0) //有附件 
		{ 
			if(j>=price[i][0]+price[i][1])//买得起主件和附件1
			{
				dp[i][j]=max(dp[i][j],dp[i-1][j-price[i][0]-price[i][1]]+sati[i][0]+sati[i][1]);
			}
			
			if(j>=price[i][0]+price[i][2])//买得起主件和附件2或1 
			{
				temp=max(dp[i-1][j-price[i][0]-price[i][1]]+sati[i][0]+sati[i][1],dp[i-1][j-price[i][0]-price[i][2]]+sati[i][0]+sati[i][2]);
				dp[i][j]=max(dp[i][j],temp);
			}		
			if(j>=price[i][0]+price[i][1]+price[i][2])//买得起主件和附件1和附件2 
			dp[i][j]=max(dp[i][j],dp[i-1][j-price[i][0]-price[i][1]-price[i][2]]+sati[i][0]+sati[i][1]+sati[i][2]);	
		}		
	}
	cout<<dp[m-1][N]<<endl;
//	cout<<"dp:"<<endl;
//	for(int i=0;i<m;i++)
//	{
//		for(int j=0;j<=N;j++)
//		{
//			cout<<dp[i][j]<<" ";
//		}
//		cout<<endl;
//	} 
} 


全部评论

相关推荐

挣K存W养DOG:入职送金条全球游,路过缅甸停一下🐔
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务