编程之美饮料供货:动态规划解法
2016-05-22 22:52
453 查看
编程之美--饮料供货
共有n种饮料,每种饮料都有自己的名字、1瓶这种饮料对应的容量(单位:L)、可供应这种饮料的最大数量、以及1瓶此种饮料的满意度、实际购买这种饮料的瓶数。
我们定义一个表示饮料的结构体。分别用name、capacity、maxNumber、happiness、purchaseNumber对应以上属性。
问题要求:给定可提供饮料的最大供应量totalSupport(单位为L),要求饮料购买方案,使得购买方案对应的满意度最大。
解决方法:
应用动态规划求解,
假设用satisfy
[L]表示在最大供应量为L的情况下,选择前n种饮料是的购买方案对应的最大满意度。则
satisfy[i][j] 就表示在最大供应量为j的情况下,选择前i中饮料的购买方案对应的最大满意度,并且有:
如果 j < capacity;satisfy[i][j] = satisfy[i - 1][j]
如果 j > capacity;satisfy[i][j] = max{satisfy[i - 1][j - k * capacity] + k * happiness, k = 0, 1, 2, 3, ..., maxNumber,并且k要使得 j-k * capacity >= 0}。这个式子最直观的解释就是,提供最大供应量j,在前i种饮料中选择。并且最大供应量j大于单位体积的第j种饮料。那么对于第j种饮料,我可以分别考虑买0、1、2、...瓶第j种饮料的情况。然后选择一个使满意度最大的购买方案。
上面就是动态规划方法递推公式。用上面的公式,就可以建立表格了!
共有n种饮料,每种饮料都有自己的名字、1瓶这种饮料对应的容量(单位:L)、可供应这种饮料的最大数量、以及1瓶此种饮料的满意度、实际购买这种饮料的瓶数。
我们定义一个表示饮料的结构体。分别用name、capacity、maxNumber、happiness、purchaseNumber对应以上属性。
问题要求:给定可提供饮料的最大供应量totalSupport(单位为L),要求饮料购买方案,使得购买方案对应的满意度最大。
解决方法:
应用动态规划求解,
假设用satisfy
[L]表示在最大供应量为L的情况下,选择前n种饮料是的购买方案对应的最大满意度。则
satisfy[i][j] 就表示在最大供应量为j的情况下,选择前i中饮料的购买方案对应的最大满意度,并且有:
如果 j < capacity;satisfy[i][j] = satisfy[i - 1][j]
如果 j > capacity;satisfy[i][j] = max{satisfy[i - 1][j - k * capacity] + k * happiness, k = 0, 1, 2, 3, ..., maxNumber,并且k要使得 j-k * capacity >= 0}。这个式子最直观的解释就是,提供最大供应量j,在前i种饮料中选择。并且最大供应量j大于单位体积的第j种饮料。那么对于第j种饮料,我可以分别考虑买0、1、2、...瓶第j种饮料的情况。然后选择一个使满意度最大的购买方案。
上面就是动态规划方法递推公式。用上面的公式,就可以建立表格了!
#include <iostream> #include <vector> #include <string> using namespace std; struct Goods{ string name;//饮料的名字名字 int capacity;//单位饮料的容量,单位:L int maxNumber;//可供应饮料的最大数量,单位:个 int happiness;//对单位饮料的满意度 int purchaseNumber;//对饮料的实际购买数量,单位:个 Goods() : name(20, '0'), capacity(0), maxNumber(0), happiness(0), purchaseNumber(0){ } }; //输入饮料信息 void getGoodsInformation(vector<Goods> &goods){ size_t n = goods.size(); if (n == 0){ return; } cout << "请依次输入饮料的名称、单位饮料的容量、可供应此种饮料的最大数量、对此种饮料的满意度:"; for(size_t i = 0; i != n; i++){ cin >> goods[i].name >> goods[i].capacity >> goods[i].maxNumber >> goods[i].happiness; } return; } //输出达到最大满意度的饮料购买方案 void getAndPrintBuy(vector<Goods> &goods, vector<vector<int> > &state, vector<int> &buy, int totalSupport){ int theNumberofGoods = buy.size(); for(int i = theNumberofGoods - 1; i >= 0; i--){ if (totalSupport == 0){ break; } int k = state[i+1][totalSupport]; buy[i] = k; totalSupport -= (k * goods[i+1-1].capacity); } cout << endl << "饮料购买方案为:" << endl; for(int i = 0; i < theNumberofGoods; i++){ cout << "饮料名:" << goods[i].name << " 购买数量:"<< buy[i] << endl; } } //使用动态规划求解 int getMaxSatisfy(vector<Goods> &goods, int totalSupport){ //定义二维数组satisfy int theNumberofGoods = goods.size();//饮料的种类 vector<vector<int> > satisfy(theNumberofGoods + 1, vector<int> (theNumberofGoods + 1, 0)); vector<vector<int> > state(theNumberofGoods + 1, vector<int> (theNumberofGoods + 1, -1)); //初始化边界条件 for(int i = 0; i <= theNumberofGoods; i++){ satisfy[i][0] = 0; } for(int j = 0; j <= totalSupport; j++){ satisfy[0][j] = 0; } for(int i = 1; i <= theNumberofGoods; i++){ for(int j = 1; j <= totalSupport; j++){ int maxHappiness = 0; int purchaseNumber = 0; for(int k = 0; k <= goods[i - 1].maxNumber; k++){ if(goods[i-1].capacity * k > j){ break; } int temp = 0; temp = satisfy[i - 1][j - k * goods[i-1].capacity] + k * goods[i-1].happiness; if (temp > maxHappiness){ maxHappiness = temp; purchaseNumber = k; } } satisfy[i][j] = maxHappiness; state[i][j] = purchaseNumber; } } //输出satisfy矩阵 for(int i = 0; i <= theNumberofGoods; i++){ for(int j = 0; j <= totalSupport; j++){ cout << satisfy[i][j] << " "; } cout << endl; } vector<int> buy(theNumberofGoods, 0); getAndPrintBuy(goods, state, buy, totalSupport); return satisfy[theNumberofGoods][totalSupport]; } int main(void){ int n; cout << "输入商品的种类n" << endl; cin >> n; vector<Goods> vec(n); getGoodsInformation(vec); int max = 0; int totalSupport;//总的饮料提供量, 单位:L cout << "输入总的饮料提供量,单位为L:" << endl; cin >> totalSupport; max = getMaxSatisfy(vec, totalSupport); cout << "最大满意度为:" << max << endl; return 0; }
相关文章推荐
- hdu 1096 A+B for Input-Output Practice (VIII)
- 设计模式(23种,java)
- Java设计模式(一):单例模式,防止反射和反序列化漏洞
- struts2与ognl结合实现下载
- hdu 1095 A+B for Input-Output Practice (VII)
- PHP数据库连接mysql与mysqli的区别与用法
- springMVC传对象参数、返回JSON格式数据
- java适配器设计模式
- thinkphp集成系列之阿里云oss
- thinkphp集成系列之阿里云oss
- 8个类,1500行代码搞定插件化
- Spring控制反制IOC
- thinkphp集成系列之rbac的升级版auth权限管理系统demo
- PHP开发者常犯的10个MySQL错误
- thinkphp集成系列之rbac的升级版auth权限管理系统demo
- thinkphp集成系列之rbac的升级版auth权限管理系统demo
- c++-作业6
- thinkphp集成系列之短信验证码、订单通知
- thinkphp集成系列之短信验证码、订单通知
- hdu 1094 A+B for Input-Output Practice (VI)