CSUOJ:经营小卖部
来源:互联网 发布:淘宝店哪家符咒是真的 编辑:程序博客网 时间:2024/04/28 21:39
Description
暑假很多店都关门了,还坚持营业的店可以收揽大多数客户。看准了这个商机,你和小伙伴们打算集资开一个小卖部。
你们总共集资了X元,可以用来购置商品和其他配置。每个商品有自己的进价和售价,你可以根据自己的要求以进价购入任意数量的商品,并全部以售价卖出。可是因为供货商暑期停止供货,所以你们只能使用X元提前买好商品并在暑假卖掉,暑假中不能再进货。此外,部分商品要求小卖部要有对应设施,比如冰淇淋和饮料要求有冰箱,粽子和方便面要求有微波炉。那么,如何才能得到最大利润?
Input
多组数据,第一行有一个整数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表示需要微波炉)。
Output
一个整数,表示最大的利润。
Sample Input
210 3 1 11 2 01 3 12 4 210 3 1 15 6 03 5 15 11 2
Sample Output
176
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////分析:卧槽,这么显而易见的背包。分四种情况分别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;}
- CSUOJ:经营小卖部
- 选拔赛proA:经营小卖部
- 经营小卖部 coj
- CSU 1671 经营小卖部
- CSU_1671_经营小卖部(完全背包)
- CSU 1671 经营小卖部 (完全背包 DP)
- csu1671 经营小卖部(DP 完全背包 好题)
- CSUOJ
- CSUOJ
- 经营
- csuoj--1307
- csuoj Lexicography
- csuoj X
- 1989CSUOJ
- 经营计划-经营回顾
- CSUOJ优先队列
- CSUOJ 1165 枚举
- CSUOJ 1063 Sequence
- 如何:使用 DataAnnotations 特性验证模型数据
- centos端口转发神器:socat安装及使用
- 时间相加
- POJ 1182 食物链(并查集)
- PDA手持终端 C#热键例子代码
- CSUOJ:经营小卖部
- js笔记
- spring-struts-mybatis整合错误集锦
- Linux系统信息查看命令
- CXGrid用法1
- hdu 5326 - Work(递归)解题报告
- 黑马程序员——C语言中变量的存储类别
- pom.xml 添加 JSON依赖的配置
- MBR 小结