Algorithm assignment 1
一、用动态规划方法手工求解下面的问题:
某工厂调查了解市场情况,估计在今后四个月内,市场对其产品的需求量如下表所示。
时期(月) | 需要量(产品单位) |
---|---|
1 | 2 |
2 | 3 |
3 | 2 |
4 | 4 |
已知:对每个月来讲,生产一批产品的固定成本费为3 (千元),若不生产,则为零。每生产单位产品的成本费为1 (千元)。同时,在任何一个月内,生产能力所允许的最大生产批量为不超过6 个单位。又知每单位产品的库存费用为每月0.5 (千元),同时要求在第一个月开始之初, 及在第四个月末,均无产品库存。
问:在满足上述条件下,该厂应如何安排各个时期的生产与库存,使所花的总成本费用最低?
要求:写出各种变量、状态转移方程、递推关系式、和详细计算步骤。
该题既可以顺推也可以逆推,但逆推的手工计算量较小。因此这里用逆推的方式求解。
-
变量描述:设n 为总月份,wi 代表第i个月的需求量,ui 代表第i个月的产量,生产固定成本c1=3 ,生产单位产品成本费c2=1 ,单位产品的库存费c3=0.5 ,单月最大生产量maxp=6
-
状态转移方程:
记si为第i个月的库存,则si+1=si+ui−wi,且si≥0,0≤ui≤maxp
vi为第i个月的花费,则vi=c3si+{c2ui+c1,ui>00,ui=0
设fi(si)为第i个月后,库存为si的最小成本,则
fi(si)=minui{vi+fi+1(si+1)}最终所求为f1(0)
-
递推关系式:
{fn(0)=0fi(si)=minui{vi+fi+1(si+1)} -
计算步骤:
由题知,所求n=4;w={2,3,2,4},所以有u4=s5−s4+w4=4−s4,即0≤s4≤4,
f4(s4)=minu4{v4+f5(0)}=minu4{0.5∗s4+{1∗u4+3,u4>00,u4=0}⟹{f4(0)=7,u4=4f4(1)=6.5,u4=3f4(2)=6,u4=2f4(3)=5.5,u4=1f4(4)=2,u4=0所以有u3=s4−s3+w3,即0≤s3≤6
f3(s3)=minu3{v3+f4(s4)}=minu3{0.5∗s3+{1∗u3+3,u3>00,u3=0}⟹{f3(0)=11,u3=6f3(1)=10.5,u3=6f3(2)=8,u3=0f3(3)=8,u3=0f3(4)=8,u3=0f3(5)=8,u3=0f3(6)=5,u3=0所以有u2=s3−s2+w2,即0≤s2≤9
f2(s2)=minu2{v2+f3(s3)}=minu2{0.5∗s2+{1∗u2+3,u2>00,u2=0}⟹{f2(0)=16,u2=5f2(1)=15.5,u2=4f2(2)=15,u2=3f2(3)=12.5,u2=0f2(4)=12.5,u2=0f2(5)=10.5,u2=0f2(6)=11,u2=0f2(7)=11.5,u2=0f2(8)=12,u2=0f2(9)=9.5,u2=0而s1=0,u1=s2−s1+w1,
f1(s1)=minu1{v1+f2(s2)}=minu1{0.5s1+{1∗u1+3,u1>00,u1=0}⟹f1(0)=20.5,u1=5故u=[5,0,6,0],s=[0,3,0,4],即4个月分别生产5、0、6、0单位产品,各月库存量分别为0、3、0、4,总成本最低为f1(0)=20.5
二、用动态规划方法编程求解下面的问题:
某推销员要从城市v1 出发,访问其它城市v2,v3,…,v6 各一次且仅一次,最后返回v1。D为各城市间的距离矩阵。
问:该推销员应如何选择路线,才能使总的行程最短?
要求:写出递推关系式、伪代码和程序相关说明,并分析时间复杂性。 (请遵守第一节课提出的有关 assignment 的要求)
-
变量描述:记城市数量n=6,城市编号为0,1,2,…,n−1,距离矩阵为D;
-
状态转移方程:设fi,S代表推销员走到第i个城市,已经访问过的城市集合为S,则
fi,S=min{fj,S−{i}+Dj,i} -
递推关系式:初始时S为空,fi,S=0
{fi,S=0fi,S=min{fj,S−{i}+Dj,i} -
伪代码:
func TSP(n, D){ // Input: n城市数量,D为距离矩阵下标从0开始 // Output: 一个数,代表从v1=0出发,最后回到v1的最小距离 初始化f为INF 将v1添加进集合S,此时f[i][S]=0 从{v1}开始枚举集合S的状态 枚举第i个城市是否在集合内,如果在 枚举不在集合内的第j个城市 将j加入集合S记为S‘,此时花费为f[i][S] + D[i][j] 记f[j][S']=min{f[j][S'], f[i][S] + D[i][j]} 则得到f[i][S]为从0出发,最后集合状态为S的最小 最后加上从最后经过的城市返回v1的距离,输出答案 }
-
时间复杂度:O(n2∗2n)
-
附程序代码:
#include<iostream> #include<cstring> using namespace std; #define INF 0x3f3f3f3f const int n = 6; const int D[6][6]={ {0,10,20,30,40,50}, {12,0,18,30,25,21}, {23,19,0,5,10,15}, {34,32,4,0,8,16}, {45,27,11,10,0,18}, {56,22,16,20,12,0} }; int f[10][1024]; int main() { memset(f, INF, sizeof(f)); f[0][1] = 0; int tot = (1 << n) - 1; for (int s = 1; s <= tot; s++) { for (int i = 0; i < n; i++) { if ((s >> i & 1 == 0) || (f[i][s] == INF)) continue; for (int j = 0; j < n; j++) if ((s >> j & 1) == 0) f[j][s | 1 << j] = min(f[j][s | 1 << j], f[i][s] + D[i][j]); } } int ans = INF; for (int i = 0; i < n; i++) if (f[i][tot] < INF) ans = min(ans, f[i][tot] + D[i][0]); cout << ans << endl; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步