题解 | #购物单#
购物单
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; // } }