sum=rightsum;
}
returnsum;
}
intMaxSum2(intn){
inta;
returnMaxSubSum(a,1,n);
}该算法所需的计算时间T(n)满足典型的分治算法递归分式
T(n)=2T(n/2)+O(n),分治算法的时间复杂度为O(nlogn)
3)设
则最大子段和为
最大子段和实际就是
.
要说明最大子段和具有最优子结构性质,只要找到其前后步骤的迭代关系即可。
若
;
若
,
。
因此,计算
的动态规划的公式为:
intMaxSum(int*a,intn)
{
intsum=0,b=0,j=0;
for(inti=1;i<=n;i++)
{if(b>0)
b=b+a[i];
else
b=a[i];
end{if}
if(b>sum)
sum=b;
j=i;
end{if}
}
returnsum;
}
自行推导,答案:
时间复杂度为O(n)。
2.动态规划算法的时间复杂度为O(n)(双机调度问题)用两台处理机A和B处理
个作业。
设第
个作业交给机器A处理时所需要的时间是
,若由机器B来处理,则所需要的时间是
。
现在要求每个作业只能由一台机器处理,每台机器都不能同时处理两个作业。
设计一个动态规划算法,使得这两台机器处理完这
个作业的时间最短(从任何一台机器开工到最后一台机器停工的总的时间)。
以下面的例子说明你的算法:
解:
(思路一)删除
(思路二)在完成前k个作业时,设机器A工作了x时间,则机器B最小的工作时间是x的一个函数。
设F[k][x]表示完成前k个作业时,机器B最小的工作时间,则
其中
对应第k个作业由机器B来处理(完成k-1个作业时机器A工作时间仍是x,则B在k-1阶段用时为
);而
对应第k个作业由机器A处理(完成k-1个作业,机器A工作时间是x-a[k],而B完成k阶段与完成k-1阶段用时相同为
)。
则完成前k个作业所需的时间为
1)当处理第一个作业时,a[1]=2,b[1]=3;
机器A所花费时间的所有可能值范围:
0≤x≤a[0].
x<0时,设F[0][x]=∞,则max(x,∞)=∞;
0≤x<2时,F[1][x]=3,则Max(0,3)=3,
x≥2时,F[1][x]=0,则Max(2,0)=2;
2)处理第二个作业时:
x的取值范围是:
0<=x<=(a[0]+a[1]),
当x<0时,记F[2][x]=∞;以此类推下去
(思路三)假定
个作业的集合为
。
设
为
的子集,若安排
中的作业在机器A上处理,其余作业在机器B上处理,此时所用时间为
,
则双机处理作业问题相当于确定
的子集
,使得安排是最省时的。
即转化为求
使得
。
若记
,则有如下递推关系:
(思路四)
此问题等价于求(x1,……xn),使得它是下面的问题最优解。
minmax{x1a1+……xnan,(1-x1)b1+……+(1-xn)bn}xi=0或1,i=1~n
基于动态规划算法的思想,对每个任务i,依次计算集合S(i)。
其中每个集合中元素都是一个3元组(F1,F2,x)。
这个3元组的每个分量定义为
F1:
处理机A的完成时间
F2:
处理机B的完成时间
x:
任务分配变量。
当xi=1时表示将任务i分配给处理机A,当xi=0时表示分配给处理机B。
初始时,S(0)={(0,0,0)}
令F=按处理时间少的原则来分配任务的方案所需的完成时间。
例如,当(a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2),(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)时,按处理时间少的原则分配任务的方案为(x1,x2,x3,x4,x5,x6)=(1,1,0,1,0,1)
因此,F=max{2+5+10+2,7+5}=19。
然后,依次考虑任务i,i=1~n。
在分配任务i时,只有2种情形,xi=1或xi=0。
此时,令S(i)={S(i-1)+(ai,0,2i)}U{S(i-1)+(0,bi,0)}在做上述集合并集的计算时,遵循下面的原则:
①当(a,b,c),(d,e,f)ЄS(i)且a=d,b<=e时,仅保留(a,b,c);
仅当max{a,b}<=F时,(a,b,c)ЄS(i)
最后在S(n)中找出使max{F1,F2}达到最小的元素,相应的x即为所求的最优解,其最优值为max{F1,F2}。
当(a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2),(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)时,按处理时间少的原则分配任务的方案为(x1,x2,x3,x4,x5,x6)=(1,1,0,1,0,1)
因此,F=max{2+5+10+2,7+5}=19。
S(0)={(0,0,0)};
S
(1)={(2,0,2),(0,3,0)}
S
(2)={(7,0,6),(5,3,4),(2,8,2),(0,11,0)}
S(3)={(14,0,14),(12,3,12),(9,8,10),(7,4,6),(5,7,4),(2,12,2),(0,15,0)}
S(4)={(19,8,26),(17,4,22),(15,7,20),(12,12,18),(14,11,14),(9,19,10),(7,15,6),(5,18,4)}
S(5)={(19,11,46),(12,15,38),(19,11,26),(17,7,22),(15,10,20),(12,15,18),(14,14,14),(7,18,6)}
S(6)={(14,15,102),(19,7,86),(17,10,84),(14,15,82),(9,18,70),(12,19,38),(15,14,20),(12,19,18)}
max(F1,F2)最小的元组为(14,15,102),(14,15,82),(15,14,20)
所以,完成所有作业最短时间是15,安排有三种:
(1,1,0,0,1,1),(1,0,0,1,0,1),(0,1,0,1,0,0)
(思路五)C++源代码如下:
#include
usingnamespacestd;
constintMAXS=70;
constintMAXN=10;
boolp[MAXS][MAXS][MAXS];
inta[MAXS],b[MAXS];
intschduleDyn(int*a,int*b,intn,intmn)
{inti,j,k;
//===========数组初始化===================
for(i=0;i<=mn;i++)
for(j=0;j<=mn;j++)
{p[i][j][0]=true;
for(k=1;k<=n;k++)
p[i][j][k]=false;
}
//===========动态递归=============
for(k=1;k<=n;k++)
for(i=0;i<=mn;i++)
for(j=0;j<=mn;j++)
{if((i-a[k-1])>=0)
p[i][j][k]=p[i-a[k-1]][j][k-1];
if((j-b[k-1])>=0)
p[i][j][k]=(p[i][j][k]|p[i][j-b[k-1]][k-1]);
}
//================求结果=====================
intrs=mn;
inttemp=0;
for(i=0;i<=mn;i++)
for(j=0;j<=mn;j++)
{if(p[i][j][n])
{temp=i>j?
i:
j;
if(temprs=temp;
}
}
returnrs;
}
voidmain()
{
inti,n,m=0,mn=0;
//=============初始化========================
cin>>n;
for(i=0;i{cin>>a[i];
if(a[i]>m)
m=a[i];
}
for(i=0;i{
cin>>b[i];
if(b[i]>m)
m=b[i];
}
mn=m*n;
//=========动态规划求解=================
cout<system("pause");
}
对于例子:
n=6;(a1,….,a6)=(2571052),(b,1…,b6)=(3841134);
由于求解过程比较繁锁,这里只说个大概算法执行过程,首先,用p[i][j][k],记录下对于第k个作业,能否在对于a机器是i时间以内,对于b机器是j时间以内完成,如果能,则把p[i][j][k]设为true.经过了设置后,求对于n个作业的所有可能的值为p[i][j][n],对min(max(i,j)),结果为15.即为所得到的结果.
3.考虑下面特殊的整数线性规划问题
试设计一个解此问题的动态规划算法,并分析算法的时间复杂度。
解:
方法1.
设
令
,则上述规划问题转化为:
,其中
,
把
看作价值,
看作重量,
看作背包容量。
转化为0/1背包问题,所以可以0/1背包问题的动态规划算法来求解。
由于n件物品的0/1背包的时间复杂性是O(2n),则此时为O(4n)。
方法2.
可以看成是另一种背包问题。
即b为背包容量,
为背包中可以装0,1,或者2件物品,
对应的价值为
,求在容量b一定的前提下,背包所容纳的物品的最大价值。
也就是参数完全相同的两个0-1背包问题,它们同时制约于背包容量为C这个条件。
在设计算法时可以优先考虑
,也就是先判断背包剩下的容量能不能放进去
,若可以再判断能否使
,若可以则就再放入一个
,这样就间接满足了
的条件。
(以上各题均来自同学们作业中的思想,仅供参考,自行整理答案。
)