暑假很多店都关门了,还坚持营业的店可以收揽大多数客户。看准了这个商机,你和小伙伴们打算集资开一个小卖部。
你们总共集资了X元,可以用来购置商品和其他配置。每个商品有自己的进价和售价,你可以根据自己的要求以进价购入任意数量的商品,并全部以售价卖出。可是因为供货商暑期停止供货,所以你们只能使用X元提前买好商品并在暑假卖掉,暑假中不能再进货。此外,部分商品要求小卖部要有对应设施,比如冰淇淋和饮料要求有冰箱,粽子和方便面要求有微波炉。那么,如何才能得到最大利润?
暑假很多店都关门了,还坚持营业的店可以收揽大多数客户。看准了这个商机,你和小伙伴们打算集资开一个小卖部。
你们总共集资了X元,可以用来购置商品和其他配置。每个商品有自己的进价和售价,你可以根据自己的要求以进价购入任意数量的商品,并全部以售价卖出。可是因为供货商暑期停止供货,所以你们只能使用X元提前买好商品并在暑假卖掉,暑假中不能再进货。此外,部分商品要求小卖部要有对应设施,比如冰淇淋和饮料要求有冰箱,粽子和方便面要求有微波炉。那么,如何才能得到最大利润?
多组数据,第一行有一个整数T,表示有T组数据(T<=100)。
以下每组数据第一行有四个整数X,N,P1和P2。X是你们的资金总数(1<=X<=1000),N表示商品种类数(1<=N<=100),P1和P2分别表示冰箱和微波炉的价格(1<=P1,P2<=1000)。之后N行每行三个整数C1,C2(1<=C1,C2<=1000)和A,分别表示这个商品的进价、售价和对设备的要求(A为0表示无需求,A为1表示需要冰箱,A为2表示需要微波炉)。
一个整数,表示最大的利润。
2
10 3 1 1
1 2 0
1 3 1
2 4 2
10 3 1 1
5 6 0
3 5 1
5 11 2
17
6
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
分析:卧槽,这么显而易见的背包。分四种情况分别DP,dp0_没有冰箱没有微波炉;dp1_有冰箱没有微波炉;dp2_有微波炉没有冰箱;dp3_冰箱微波炉都有。然后在一个DP的循环里面判断四种情况的可行性,然后剩下的就是很普通的背包啦。。。不过我的方法略笨重,代码80行,700msAC的,我看status里面大家都是100ms以内,暂时还不知道是怎么优化的。
总结:背包还是比较重要的,各种变形各种熟悉又陌生,又爱又恨的。背包还是要多啃一点。
下面是代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<cmath> using namespace std; typedef long long LL; int t,X,N,p1,p2; int dp3[105][1005]; int dp2[105][1005]; int dp1[105][1005]; int dp0[105][1005]; int C[105]; int W[105]; int P[105]; int main() { // freopen("in.txt","r",stdin); scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&X,&N,&p1,&p2); for(int i=1;i<=N;++i){ scanf("%d%d%d",&C[i],&W[i],&P[i]); } memset(dp3,0,sizeof(dp3)); memset(dp2,0,sizeof(dp2)); memset(dp1,0,sizeof(dp1)); memset(dp0,0,sizeof(dp0)); for(int i=1;i<=N;++i){ for(int j=0;j<=X;++j){ if(j+p1+p2<=X)dp3[i][j]=dp3[i-1][j]; if(j+p2<=X)dp2[i][j]=dp2[i-1][j]; if(j+p1<=X)dp1[i][j]=dp1[i-1][j]; dp0[i][j]=dp0[i-1][j]; for(int k=1;k<=i;++k){ if(j-C[i]>=0){ if(j+p1+p2<=X)dp3[i][j]=max(dp3[i][j],dp3[k][j-C[i]]+W[i]-C[i]); } if(P[i]!=1){ if(j-C[i]>=0){ if(j+p2<=X)dp2[i][j]=max(dp2[i][j],dp2[k][j-C[i]]+W[i]-C[i]); } } if(P[i]!=2){ if(j-C[i]>=0){ if(j+p1<=X)dp1[i][j]=max(dp1[i][j],dp1[k][j-C[i]]+W[i]-C[i]); } } if(P[i]!=2&&P[i]!=1){ if(j-C[i]>=0) dp0[i][j]=max(dp0[i][j],dp0[k][j-C[i]]+W[i]-C[i]); } } } }int m0,m1,m2,m3; m0=0;m1=0;m2=0;m3=0; for(int i=1;i<=N;++i){ for(int j=1;j<=X;++j){ if(m1<dp1[i][j]) m1=dp1[i][j]; if(m2<dp2[i][j]) m2=dp2[i][j]; if(m3<dp3[i][j]) m3=dp3[i][j]; if(m0<dp0[i][j]) m0=dp0[i][j]; } } if(m1==0&&m2==0&&m3==0&&m0==0){ printf("0\n");continue; } m1-=p1;m2-=p2;m3=m3-p1-p2;//////////////////这一步很重要!!!得到的收入还要减去购买设备的钱才是利润!! printf("%d\n",max(max(m1,m0),max(m2,m3))); } return 0; } /************************************************************** Problem: 1006 Language: C++ Result: Accepted Time:700 ms Memory:3188 kb ****************************************************************/
更新更新更新。。。。。。。。。。。。。。。管理员改了数据。。。。。这份代码TLE了。。。。哭
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
再更新。。。今天早上把这道题重新整理思路做了一遍,才想起完全背包的第三层循环不是前i次选择物品时重量为j-C[i],应该是对取k件物品的k循环就好,只需要对上一次的dp进行累加判断。。。。渣渣还是渣渣。
下面是A的代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int C[105]; int W[105]; int P[105]; int dp[105][1005][4]; int t,x,n,p1,p2; int main() { scanf("%d",&t); while(t--){ scanf("%d%d%d%d",&x,&n,&p1,&p2); for(int i=1;i<=n;++i){ scanf("%d%d%d",&C[i],&W[i],&P[i]); } memset(dp,0,sizeof(dp)); for(int i=1;i<=n;++i){ for(int j=1;j<=x;++j){ dp[i][j][0]=dp[i-1][j][0]; if(j+p1<=x)dp[i][j][1]=dp[i-1][j][1]; if(j+p2<=x)dp[i][j][2]=dp[i-1][j][2]; if(j+p1+p2<=x)dp[i][j][3]=dp[i-1][j][3]; for(int k=1;;++k){ if(j-k*C[i]>=0){ if(!P[i]) dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-k*C[i]][0]+k*(W[i]-C[i])); if(j+p1<=x&&P[i]!=2) dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-k*C[i]][1]+k*(W[i]-C[i])); if(j+p2<=x&&P[i]!=1) dp[i][j][2]=max(dp[i][j][2],dp[i-1][j-k*C[i]][2]+k*(W[i]-C[i])); if(j+p1+p2<=x) dp[i][j][3]=max(dp[i][j][3],dp[i-1][j-k*C[i]][3]+k*(W[i]-C[i])); }else break; } } } printf("%d\n",max(max(dp[n][x][0],dp[n][x-p1][1]-p1),max(dp[n][x-p2][2]-p2,dp[n][x-p1-p2][3]-p1-p2))); } return 0; }