算法设计与分析(第2版) 王红梅 胡明 习题答案 下载本文

如果桌上有小于4根的火柴,先手必胜,如果是5根,先手必输;依次类推,同理15、20、25…….都是必输状态;所有每次把对手逼到15、20、25…….等必输状态,就可以获胜。

9. 竞赛树是一棵完全二叉树,它反映了一系列“淘汰赛”的结果:叶子代表参加比赛的n个选手,每个内部结点代表由该结点的孩子结点所代表的选手中的胜者,显然,树的根结点就代表了淘汰赛的冠军。请回答下列问题:

(1)这一系列的淘汰赛中比赛的总场数是多少?

(2)设计一个高效的算法,它能够利用比赛中产生的信息确定亚军。

(1)因为n人进行淘汰赛,要淘汰n-1人,所有要进行n-1场比赛。 (2)

10. 在120枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,最坏情况下,能不能只比较5次就检测出这枚假币?

将120枚平均分为三组,记为:A,B,C;先将A,B比较,如果A,B重量不同(假如B比A重),再将B与C比较,如果B,C相同,则A有假币;如果B,C不同,再将A,C比较,如果A,C相同,则B有假币;如果A,C不同,则B有假币;如果A,B相同,则C有假币;

习题6

1. 动态规划法为什么都需要填表?如何设计表格的结构?

在填写表格过程中,不仅可以使问题更加清晰,更重要的是可以确定问题的存储结构; 设计表格,以自底向上的方式计算各个子问题的解并填表。

2. 对于图6.26所示多段图,用动态规划法求从顶点0到顶点12的最短路径,写出求解过程。 1 6 3 8 1 7 3 3 3 5 6 5 10 4 4 5 5 8 2 0 12 3 5 3 8 3 11 3 7 9 8 2 6 6 6 4 图6.26 第2题图

将该多段图分为四段;

首先求解初始子问题,可直接获得: d(0, 1)=c01=5(0→1) d(0, 2)=c02=3(0→1)

再求解下一个阶段的子问题,有: d(0,3)= d(0, 1)+ c13 =6(1→3)

d(0,4)=min{d(0,1)+ c14 ,d(0,2)+ c24}=8(1→4) 。。。。。。。。(以此类推)

最短路径为:0→1→3→8→11→12 3.用动态规划法求如下0/1背包问题的最优解:有5个物品,其重量分别为(3, 2, 1, 4,5),价值分别为(25, 20, 15, 40, 50),背包容量为6。写出求解过程。

(x1, x2,x3,x4,x5) →(1,1,1,0,0)(过程略)

4. 用动态规划法求两个字符串A=\xzyzzyx\和B=\zxyyzxz\的最长公共子序列。写出求解过程。 略

5. 给定模式\和文本\,写出动态规划法求解K-近似匹配的过程。 略

6. 对于最优二叉查找树的动态规划算法,设计一个线性时间算法,从二维表R中生成最优二叉查找树。

7. Ackermann函数A(m, n)的递归定义如下:

n?1??A(m,n)??A(m?1,1)?A(m?1,A(m,n?1))?m?0m?0,n?0 m?0,n?0设计动态规划算法计算A(m, n),要求算法的空间复杂性为O(m)。

//求ackman函数 //使用栈

#include using namespace std;

long ackman(long m, long n) {

long stack[10000]; int pos=1;

stack[0]=m;stack[1]=n; while(pos)

{

n=stack[pos--]; m=stack[pos]; if(m==0)

stack[pos]=n+1; if(m!=0&&n==0) {

stack[pos++]=m-1; stack[pos]=1; }

if(m!=0&&n!=0) {

stack[pos++]=m-1; stack[pos++]=m; stack[pos]=n-1; } }

return stack[0]; }

int main(int argc, char *argv[]) {

long m,n; cin>>m>>n;

cout<

return 0; }

8. 考虑下面的货币兑付问题:在面值为(v1, v2, ?, vn)的n种货币中,需要支付y值的货币,应如何支付才能使货币支付的张数最少,即满足

?xvi?1nii?y,且使?xi最小(xi是

i?1n非负整数)。设计动态规划算法求解货币兑付问题,并分析时间性能和空间性能。

#include #define N 100000 #define M 20

int a[N][M]; int value[M];

using namespace std;

int main() {

while(true) {

int i,j,k; int x,y,z;

cout<<\输入货币种类的个数:\ cin>>x;

cout<<\从小到大输入货币的价值,其中第一个必须为一:\ for(i=1;i<=x;i++)//x为货币种类的个数 {

cout<<\ cin>>y; value[i]=y; }

cout<<\输入要兑换的钱的价值:\ cin>>z;//z为钱 for(j=0;j<=z;j++) a[j][0]=0;

for(k=0;k<=x;k++) a[0][k]=0; for(i=1;i<=z;i++) {

for(j=1;j<=x;j++) {

if(value[j]==i) a[i][j]=1; else if(value[j]>i) a[i][j]=a[i][j-1]; else

a[i][j]=a[i-value[j]][j]+1;//相当于把乘法换成加法,即碰到一个钱数于

兑换货币自身价值时,返回到

钱数减去该货币值的地方,其值再加1// }//for }

cout<<\兑换的最小货币个数是:\

}//while

return 0; }

9. 多边形游戏。多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形,每个顶点具有一个整数值,每条边具有一个运算符“+”或“×”。游戏规则是每次选择一条边e以及和e相关联的两个顶点i和j,用一个新的顶点k取代边e、顶点i和j,顶点k的整数值是顶点i和j的整数值通过边e上的运算符计算得到的结果。当所有边都删除时,游戏结束,游戏的得分就是所剩顶点的整数值。设计动态规划算法,对于给定的多边形计算最高得分。