标签:
记得初中时候的一篇文章说,做学问,必须要有学和问两个方面。
做了一些动态规划题目之后偶然看到这个介绍动态规划的文章。然后遇见第一道题目就卡壳。
经过反思文章以及自己思考,总算对题目有了一些理解。下面分享给大家,初学者们看到这个题目不至于太过茫然——像我一样。
工厂生产某种产品,每单位(千件)的成本为1(千元),每次开工的固定成本为3(千元),工厂每季度的最大生产能力为6(千件)。经调查,市场对该产品的需求量第一、二、三、四季度分别为 2,3,2,4(千件)。如果工厂在第一、二季度将全年的需求都生产出来,自然可以降低成本(少付固定成本费),但是对于第三、四季度才能上市的产品需付存储费,每季每千件的存储费为0.5(千元)。还规定年初和年末这种产品均无库存。试制订一个生产计划,即安排每个季度的产量,使一年的总费用(生产成本和存储费)最少。
学:
1、动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。
2、动态规划算法的基本步骤
问:
此题目的阶段如何划分、状态如何确定、决策有哪些、状态之间有什么关系。。。
思路:
首先应该是应该选择何种变量来划分问题的各个状态——即找到想要求得结果时需要反复计算的一种状态。
已经知道有四个季度,可以选择各个季度的产量,还有一个附加条件——一年的开始和结束都没有库存
那么是否可以用这三个变量(季度,产量,季末库存)来表示状态呢?
开始分析:状态之间的关系。
因为有0.5,开始定义一个double 型的三维数组dp[i][j][k]表示第i季度,产量为j,剩余量为k时的最少花费。
那么,问题来啦
因为同一个状态dp[i][j][k]有多个来源,上一季度的产量和剩余量都不确定,如何设置搜索过程来确定这个最小值,
似乎子问题并不是那么容易解决。
但是两阶段之间有一重要的关系:
本季度剩余量k==本季度产量+上季度库存量-本季度需求。
因此dp[i][j][k]=min(dp[i][j][k],dp[i-1][0...6][k+本季度需求-本季度产量])
只要再设置一层循环0到6就可以找出dp[i][j][k]最小值。
这样设置一个四层循环,然后循环结束后输出dp[4][0...6][0] 的最小值,就是本题的最终结果。
大体框架思路有了,下面就是代码实现:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int main() { double dp[5][7][7]; double cost[7][7]; int d[5]={0,2,3,2,4};//各个季度的需求 int i,j,k,l,m,temp,c; for(i=0;i<7;i++) for(j=0;j<7;j++) { cost[i][j]=0.5*i+(j==0?0:j*1+3);//因为题目中多次用到库存为i生产为j的一季度消费,故初始化。 if(j==i-2) dp[1][i][j]=cost[0][i];//第一季度比较特殊,开始时库存为0 else dp[1][i][j]=-1.0;//负数代表不合法 } for(i=2;i<=4;i++) for(j=0;j<=6;j++) for(k=0;k<=6;k++) { temp=k+j-d[i]; if(temp>=0)//边界问题 { c=-1; dp[i][j][k]=99; for(m=0;m<=6;m++) if(dp[i-1][m][temp]>0)//必须是合法数据 { dp[i][j][k]=min(dp[i][j][k],dp[i-1][m][temp]+cost[temp][j]); c=0; } if(c) dp[i][j][k]=-1;//未找到合法数据 } else dp[i][j][k]=-1; } double cnt=99; for(i=0;i<=6;i++) if(dp[4][i][0]>0) cnt=min(cnt,dp[4][i][0]);//输出最小值 printf("%lf\n",cnt); return 0; }
标签:
原文地址:http://www.cnblogs.com/KIKIKS/p/4298145.html