思考题16-1
首先证明硬币找零问题有最优子结构,设我们有找
n
美分的问题的最优解,且知道这个最优解使用了一个
a)
q=⌊n/25⌋
,剩下
n′=n mod 25
美分,
d=⌊n′/10⌋
,剩下
d′=n′mod 10,k=d′/5
,剩下
k′=d′ mod 5
,其余的全是
1
美分硬币,总结就是每次选取最大的零钱,若面额大于选的纸币,则可以兑换,否则选取较小的零钱,以此类推。
b) 证明略。
c) 现在有
d) 由最开始的证明可知找零问题有最优子结构,所以可以用动态规划来做。
设
j
美分的钱用了
COMPUTE-CHANGE(n, d, k)
let c[1..n] and denom[1..n] be new arrays
for j = 1 to n
c[j] = ∞
for i = 1 to k
if j≥di and 1 + c[j-di] < c[j]
c[j] = 1 + c[j-di]
denom[j] = di
return c and denom
GIVE-CHANGE(j, denom)
if j > 0
give one coin of denomination denom[j]
GIVE-CHANGE(j-denom[j], denom)
附上运行代码
#include <iostream>
#include <algorithm>
using std::cout;
using std::endl;
void GIVE_CHANGE(int *denom,int j)
{
if(j > 0)
{
cout << "give one coin of denomination " << denom[j] << endl;
GIVE_CHANGE(denom,j-denom[j]);
}
}
void COMPUTE_CHANGE(int *d,int n,int value)//n个硬币面额的数组和需要找零的面值value
{
int *c = new int[value+1];
int *denom = new int[value+1];
c[0] = 0;
for(int j = 1; j <= value; j++)
{
c[j] = INT_MAX;
for(int i = 0; i < n; i++)
{
if(j >= d[i] && 1 + c[j-d[i]] < c[j])
{
c[j] = c[j-d[i]] + 1;
denom[j] = d[i];
}
}
}
GIVE_CHANGE(denom,value);
delete []c;
delete []denom;
}
int main()
{
int value = 130;
int d[] = {10,25,1};
std::sort(d,d+3);
COMPUTE_CHANGE(d,3,value);
return 0;
}
思考题16-2
a) 先对任务集合按照完成时间长度排序,完成时间越小排在越前面。排序之后是 p1≤p2≤...≤pn 。然后依次选择这些任务调度。 cavg=(p1+(p1+p2)+...+(p1+p2+...+pn))/n 。排序时间是 O(nlgn) 。所以是 O(nlgn) 的复杂度。
b) 采用最短剩余时间调度算法(Shortest Remaining Time First(SRTF))。运行时间是 O(nT) 。
思考题16-3—16-5
答案略