最小费用购物问题

一、 实验目的

对于给定欲购商品的价格和数量,以及优惠商品价,编程计算所购商品应付的最少费用。

二、 实验要求

数据输入:
由文件input.txt提供预购商品数据。控制台的第 1 行中有 1 个整数 B(0≤B≤5),表示所购商品种类数。接下来的 B 行,每行有 3 个数 C,K 和 P。C 表示商品的编码(每种商品有 唯一编码),1≤C≤999。K 表示购买该种商品总数,1≤K≤5。P 是该种商品的正常单价(每件商品的价格),1≤P≤999。请注意,一次最多可购买 5*5=25 件商品。
由文件offe.txt提供优惠商品价数据。接下来输入 1 个整数 S(0≤S≤99),表示 共有 S 种优惠商品组合。接下来的 S 行,每行的第一个数描述优惠商品组合中商品的种类数 j。接着是 j 个数字对(C,K),其中 C 是商品编码,1≤C≤999。K 表示该种商品在此组合中的数量,1≤K≤5。每行最后一个数字 P(1≤ P≤9999)表示此商品组合的优惠价。
数据输出: 将计算出的所购商品应付的最少费用输出到文件output.txt

三、 实验原理

找出问题的规律,设cost(a,b,c,d,e)表示购买商品组合(a,b,c,d,e)需要的最少费用,A[k],B[k],C[k],D[k],E[k]表示第k种优惠方案的商品组合。offer(m)是第m种优惠方案的价格。如果cost(a,b,c,d,e)使用了第m种优惠方案,则找出最优子问题的递归表达式:cost(a,b,c,d,e)=cost(a-A[m],b-B[m],c-C[m],d-D[m],e-E[m])+offer(m) 。即该问题具有最有子结构性质,可以用动态规划算法来实现。

四、实验结果

在这里插入图片描述

六、附录

#include <iostream>
#include <bits/stdc++.h>

#define MAXCODE 999//商品编码的最大值
#define SALECOMB 99//优惠商品组合数
#define KIND 5     //商品种类
#define QUANTITY 5//购买某种商品数量的最大值

using namespace std;
struct Commodity
{
    int piece;
    int price;
};
int b;//购买商品种类数
int s;//当前优惠组合数
int num[MAXCODE+1];//记录商品编码与商品种类的对应关系
int product[KIND+1];//记录不同种类商品的购买数量
int offer[SALECOMB+1][KIND+1];//offer[i][j]: 商品组合的优惠价(j=0);某种优惠组合中某种商品需要购买的数量(j>0)
Commodity purch[KIND+1];//记录不同商品的购买数量和购买价格
int cost[QUANTITY+1][QUANTITY+1][QUANTITY+1][QUANTITY+1][QUANTITY+1];//记录本次购买的总花费

void init();
void minicost();
void comp(int i);
void out();
int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    init();
    comp(1);
    out();
    return 0;
}
void init()
{
    int i,j,n,p,t,code;
    for(i=0;i<100;i++)
        for(j=0;j<6;j++)
            offer[i][j]=0;
    for(i=0;i<6;i++)
    {
        purch[i].piece=0;
        purch[i].price=0;
        product[i]=0;
    }
    freopen("input.txt","r",stdin);
    cin>>b;
    for(i=1;i<=b;i++)
    {
        cin>>code;
        cin>>purch[i].piece>>purch[i].price;
        num[code]=i;
    }
    fclose(stdin);
    cin.clear();
    freopen("offer.txt","r",stdin);
    cin>>s;
    for(i=1;i<=s;i++)
    {
        cin>>t;
        for(j=1;j<=t;j++)
        {
            cin>>n>>p;//p代表该类商品优惠数量
            offer[i][num[n]]=p;
        }
        cin>>offer[i][0];
    }
    fclose(stdin);
}
void minicost()
{
    int i,j,k,m,n;//已经购买1~5种商品的数量
    int p;
    int minm=0;//最小花销
    for(i=1;i<=b;i++)
        minm+=product[i]*purch[i].price;//正常价格购买
    for(p=1;p<=s;p++)//购买数量减去优惠规定数量
    {
        i=product[1]-offer[p][1];
        j=product[2]-offer[p][2];
        k=product[3]-offer[p][3];
        m=product[4]-offer[p][4];
        n=product[5]-offer[p][5];
        if(i>=0&&j>=0&&k>=0&&m>=0&&n>=0&&cost[i][j][k][m][n]+offer[p][0]<minm)
            minm=cost[i][j][k][m][n]+offer[p][0];
    }
    cost[product[1]][product[2]][product[3]][product[4]][product[5]]=minm;
}
void comp(int i)
{
    if(i>b)
    {
        minicost();
        return;
    }
    for(int j=0;j<=purch[i].piece;j++)
    {
        product[i]=j;
        comp(i+1);
    }
}
void out()
{
    freopen("output.txt","w",stdout);
    cout<<cost[product[1]][product[2]][product[3]][product[4]][product[5]];
}
  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值