算法设计与分析实验报告.docx

上传人:b****7 文档编号:11246702 上传时间:2023-02-26 格式:DOCX 页数:17 大小:19.17KB
下载 相关 举报
算法设计与分析实验报告.docx_第1页
第1页 / 共17页
算法设计与分析实验报告.docx_第2页
第2页 / 共17页
算法设计与分析实验报告.docx_第3页
第3页 / 共17页
算法设计与分析实验报告.docx_第4页
第4页 / 共17页
算法设计与分析实验报告.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

算法设计与分析实验报告.docx

《算法设计与分析实验报告.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验报告.docx(17页珍藏版)》请在冰豆网上搜索。

算法设计与分析实验报告.docx

算法设计与分析实验报告

 

《算法设计与分析》课程报告

 

课题名称:

_________算法设计与分析__________

课题负责人名(学号):

同组成员名单(角色):

指导教师:

评阅成绩:

评阅意见:

 

提交报告时间:

2013年6月12日

第二章递归与分治策略

2-3改写二分搜索算法

1.问题描述:

设a[0:

n-1]是已排好序的数组。

请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。

当搜索元素在数组中时,i和j相同,均为x在数组中的位置。

2.分析与证明:

设a[0:

n-1]是已排好序的数组。

请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。

当搜索元素在数组中时,i和j相等,均为x在数组中的位置。

3.代码实现:

template

intBinarySearch(Typea[],constType&x,intleft,intright,int&i,int&j)

{

while(left<=right){

intmid=(left+right)/2;

if(x==a[mid]){i=j=mid;return1;}

if(x

elseleft=mid+1;

}

i=right;j=left;//或i=left-1;j=left

return0;

}

5.问题:

改写二分搜索算法,返回小于x的最大元素位置i和大于x的最小元素位置j。

当找到与x同的元素时,i和j相同,均为x在数组中的位置

 

第三章动态规划

3-5编辑距离问题

1.问题描述:

设A和B是两个字符串。

要用最少的字符操作将字符串A转换为字符串B。

这里所说的字符操作包括:

1)删除一个字符;

2)插入一个字符;

3)将一个字符改为另一个字符。

将字符串A变换为字符串B所用的最少字符操作数称谓字符串A到B的编辑距离,记为d(A,B)。

试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。

2.分析与证明:

a.开一个二维数组d[i][j]来记录a0-ai与b0-bj之间的编辑距离,要递推时,需要考虑对其中一个字符串的删除操作、插入操作和替换操作分别花费的开销,从中找出一个最小的开销即为所求

b.具体算法:

c.首先给定第一行和第一列,然后,每个值d[i,j]这样计算:

d[i][j]=min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+(s1[i]==s2[j]?

0:

1));

d.最后一行,最后一列的那个值就是最小编辑距离

 

3.代码实现:

#include

#include

#include

#include

inti,j;

char*s1=newchar[80];

char*s2=newchar[80];

intmd[81][81];

intmin(inta,intb,intc);

inteditDistance(intlen1,intlen2);//最短编辑距离

voidmain()

{

fstreaminDst;

inDst.open("E:

\\input.txt",ios:

:

in,0);

inDst>>s1;

inDst>>s2;

inDst.close();

fstreamoutDst;

outDst.open("E:

\\output.txt",ios:

:

app,0);

outDst<

outDst.close();

}

intmin(inta,intb,intc)

{

inttemp=(a

a:

b;

return(temp

temp:

c;

}

//最短编辑距离

inteditDistance(intlen1,intlen2)

{

//当某一个字符串为空时,最短编辑距离是另外一个字符串的长度。

for(i=0;i<=len1;i++)

{

md[i][0]=i;

}

for(j=0;j<=len2;j++)

{

md[0][j]=j;

}

for(i=1;i<=len1;i++)

{

for(j=1;j<=len2;j++)

{

intcost=(s1[i-1]==s2[j-1])?

0:

1;

intdelet=md[i-1][j]+1;

intinsert=md[i][j-1]+1;

intsubstit=md[i-1][j-1]+cost;

md[i][j]=min(delet,insert,substit);

}

}

returnmd[len1][len2];

}

4.测试数据:

Input.txt

fxpimu

xwrs

运行结果:

Output.txt

5

5.复杂度分析:

二重for循环复杂度为O(n^2)

第四章贪心算法

4-9汽车加油问题

1.问题描述:

一辆汽车加满油后可行驶nkm。

旅途中有若干加油站。

设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。

2.证明与分析:

1 解题思路:

先判断是否有解,再对数组从1到k+1计算尽量往前走,直至不能走就+1,计算出最大

2 算法策略:

贪心算法

3 基本变量描述:

data[]和数组a[]都是用来保存k+1个距离值,sum和total均用来记录最少加油次数,total=-1表无解

3.代码实现:

#include

#include

#include

#include

 

intCarInGas(inta[],intn,intk);

intmain()

{

inti,k,n,data[100],total;

fstreamrData;

rData.open("E:

\\input.txt",ios:

:

in,0);

rData>>n>>k;

for(i=1;i<=k+1;i++)

{

rData>>data[i];

}

total=CarInGas(data,n,k);

rData.close();

fstreamwData;

wData.open("E:

\\output.txt",ios:

:

app,0);

if(!

wData)

{

cout<<"Falsetoopenfile."<

}

if(total==-1)

{

cout<<"Nosolution!

"<

wData<<"Nosolution!

"<

}

else

{

cout<

wData<

}

wData.close();

system("pause");

return0;

}

intCarInGas(inta[100],intn,intk)

{

inti,sum=0,curDistan=0;

for(i=1;i<=k+1;i++)

{

if(a[i]>n)

return-1;

}

for(i=1;i<=k+1;i++)

{

curDistan=a[i]+curDistan;

if(curDistan>n)

{

sum++;

curDistan=a[i];

}

}

returnsum;

}

4.测试数据:

Input.txt

77

12345166

运行结果:

Output.txt

4

5.复杂度分析:

for(i=1;i<=k+1;i++)

rData>>data[i];

复杂度为:

O(n)

CarInGas(a,n,k)也为O(n)

两者互不嵌套,所以为O(n)

第五章回溯法

5-13工作分配问题

1.问题描述:

设有n件工作分配给n个人。

将工作i分配给第j个人所需的费用为Cij。

试设计一个算法。

为每一个人都分配1件不同的工作,并使总费用达到最小。

2.分析与证明:

由于每个人都必须分配到工作,在这里可以建一个二维数组allot[i][j],用以表示i号工人完成j号工作所需的费用。

给定一个循环,从第1个工人开始循环分配工作,直到所有工人都分配到。

为第i个工人分配工作时,再循环检查每个工作是否已被分配,没有则分配给i号工人,否则检查下一个工作。

可以用一个一维数组flag[j]来表示第j号工作是否被分配,未分配则flag[j]=0,否则flag[j]=1。

利用回溯思想,在工人循环结束后回到上一工人,取消此次分配的工作,而去分配下一工作直到可以分配为止。

这样,一直回溯到第1个工人后,就能得到所有的可行解。

在检查工作分配时,其实就是判断取得可行解时的二维数组的一下标都不相同,二下标同样不相同。

这样,得到了所有的可行解。

为了得到最少的费用,即可行解中和最小的一个,故需要再定义一个全局变量cost表示最终的总费用,初始cost为allot[i][i]之和,即对角线费用相加。

在所有工人分配完工作时,比较sumFare与cost的大小,如果sumFare小于cost,证明在回溯时找到了一个最优解,此时就把sumFare赋给cost。

考虑到算法的复杂度,可以设计一个剪枝函数。

就是在每次计算局部费用变量sumFare的值时,如果判断sumFare已经大于cost,就没必要再往下分配了,因为这时得到的解必然不是最优解。

3.代码实现:

#include

#include

//usingnamespacestd;

#include

intn;

intcost=0;//现行最小费用

intflag[100];//工作是否被分配,“1”代表已分配

intallot[100][100];//表示i号工人完成j号工作的费用

intWorkAllocation(inti,intsumFare);

intmain()

{

fstreamrData;

rData.open("E:

\\input.txt",ios:

:

in,0);

rData>>n;

for(inti=1;i<=n;i++)

{

for(intj=1;j<=n;j++)

{

rData>>allot[i][j];

flag[j]=0;

}

cost+=allot[i][i];//对角线费用相加,用于剪枝

}

rData.close();

fstreamwData;

wData.open("E:

\\output.txt",ios:

:

app,0);

if(!

wData)

{

cout<<"Falsetoopenfile."<

}

wData<

wData.close();

system("pause");

return0;

}

 

intWorkAllocation(inti,intsumFare)

{

if(i>n&&sumFare

{

cost=sumFare;

return1;

}

if(sumFare

{

for(intj=1;j<=n;j++)

{

if(flag[j]==0)

{

flag[j]=1;

WorkAllocation(i+1,sumFare+allot[i][j]);

flag[j]=0;

}

}

}

returncost;

}

4.测试数据:

Input.txt

3

1023

234

345

运行结果:

Output.txt

9

5.复杂度分析:

从main函数中的for循环中可以看出其算法复杂度为O(n^2)

 

第六章分支限界法

6-6n皇后问题

1.问题描述:

在nxn格的棋盘上放置彼此不受攻击的n个皇后。

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n皇后问题等价于在nxn各的棋盘上放置n个皇后,任何两个皇后不放在同一行或者同一列或者同一斜线上。

设计一个解n皇后问题的队列式分支限界法,计算在nxn个方格上放置彼此不受攻击的n个皇后的一个放置方案。

2.分析与证明:

题目要求我们只需要输出摆放皇后的一中解,所以在分支限界法时,每一种皇后的摆放即为一条分支,而遍历解空间相当于广度优先遍历树,因此只要将n个皇后摆放完成,便可以输出解,并不存在最优解的情况。

3.代码实现:

#include

#include

#include

usingnamespacestd;

fstreamminput("D:

\\input.txt");

fstreammoutput("D:

\\output.txt");

classNode

{

public:

Node(intn)

{

t=0;

this->n=n;

loc=newint[n+1];

for(inti=0;i<=n;++i)

{

loc[i]=0;

}

}

Node(constNode&other)

{

this->t=other.t;

this->n=other.n;

this->loc=newint[n+1];

for(inti=0;i<=n;++i)

{

this->loc[i]=other.loc[i];

}

}

intt;

int*loc;

intn;

boolcheckNext(intnext);

voidprintQ();

};

boolNode:

:

checkNext(intnext)

{

inti;

for(i=1;i<=t;++i)

{

if(loc[i]==next)

{

returnfalse;

}

if(loc[i]-next==t+1-i)

{

returnfalse;

}

if(loc[i]-next==i-t-1)

{

returnfalse;

}

}

returntrue;

}

voidNode:

:

printQ()

{

for(inti=1;i<=n;++i)

{

moutput<

}

moutput<

}

classQueen

{

public:

intn;

intansNum;

Queen(intn){

this->n=n;

ansNum=0;

}

voidArrangQueen();

};

voidQueen:

:

ArrangQueen()

{

queueQ;

Nodeini(n);

Q.push(ini);

while(!

Q.empty())

{

Nodefather=Q.front();

Q.pop();

if(father.t==n)

{

father.printQ();

++ansNum;

break;

}

for(inti=1;i<=n;++i)

{

if(father.checkNext(i))

{

NodeChild(father);

++Child.t;

Child.loc[Child.t]=i;

Q.push(Child);

}

}

}

}

intmain(void)

{

intnum;

minput>>num;

QueenQ(num);

Q.ArrangQueen();

return0;

}

4.测试数据:

Input.txt

5

运行结果:

Output.txt

13524

5.复杂度分析:

递归调用for循环,算法复杂度为O(n!

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1