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;}


0 0
原创粉丝点击