算法设计与分析的实验报告Word下载.docx
《算法设计与分析的实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《算法设计与分析的实验报告Word下载.docx(17页珍藏版)》请在冰豆网上搜索。
七、附录:
(源代码)
#include<
iostream.h>
stdio.h>
intbinarySearch(inta[],intx,intn)
{
intleft=0;
intright=n-1;
inti,j;
while(left<
=right)
intmiddle=(left+right)/2;
if(x==a[middle]){i=j=middle;
return1;
}
if(x>
a[middle])left=middle+1;
elseright=middle-1;
i=right;
j=left;
return0;
intmain()
{inta[10]={0,1,2,3,4,5,6,7,8,9};
intn=10;
intx=9;
if(binarySearch(a,x,n))
cout<
<
"
找到"
endl;
else
找不到"
实验二动态规划——求解最优问题
1.加深学生对动态规划算法设计方法的基本思想、基本步骤、基本方法的理解与掌握;
1、用两台处理机A和B处理n个作业。
设第i个作业交给机器A处理时所需要的时间是a[i],若由机器B来处理,则所需要的时间是b[i]。
由于各作业的特点和机器的性能关系,很可能对于某些i,有a[i]>
=b[i],而对于某些就j,j!
=i,有a[i]<
b[j]。
既不能将一个作业分开由两台机器处理,也没有一台机器能同时处理2个作业。
设计一个动态规划算法,使得这两台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总的时间)。
研究一个实例:
(a[1],a[2],a[3],a[4],a[5],a[6])=(2,5,7,10,5,2);
(b[1],b[2],b[3],b[4],b[5],b[6])=(3,8,4,11,3,4)。
2、长江游艇俱乐部在长江上设置了n个游艇出租站1,2……n。
游客可在游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。
游艇出租站i到游艇出租站j之间的租金r(i,j)1<
=i<
j<
=n。
设计一个算法,计算出游艇1到游艇n所需最少租金。
(1)用动态规划思想求解最优问题;
(2)再选择自己熟悉的程序设计语言实现所有算法;
(3)分析所设计的算法的时间/空间复杂性。
1、对于给定的2台处理机A和B处理n个作业,找出一个最优调度方案,使2台机器处理完这n个作业的时间最短。
2、对于给定的游艇出租站i到游艇出租站j之间的租金为r(i,j),1<
=n,计算出游艇1到游艇n所需最少租金。
独立任务最优调度问题:
租用游艇问题:
O(n*Sum)
对于算法来说,没有最好,只有更好,算法的结果不一定是最佳答案,但至少是最接近最佳答案的。
在权衡算法时间复杂度和空间复杂度的情况下,找到一个在时间和空间都能接受的算法才是上上之策。
usingSystem;
namespacezydd
classProgram
{
staticvoidDlrwZydd(int[]a,int[]b,intn,int[]least,string[]result)
for(inti=0;
i<
n;
i++)
least[i]=99;
intaSum=0,bSum=0;
aSum+=a[i];
bSum+=b[i];
intSum=1+Math.Min(aSum,bSum);
int[,]timeA=newint[n,Sum];
int[,]timeB=newint[n,Sum];
int[,]timeMax=newint[n,Sum];
char[,]who=newchar[n,Sum];
char[]tempRlt=newchar[n];
for(inti=0;
=a[0];
timeA[0,i]=i;
if(i<
a[0])
timeB[0,i]=b[0];
who[0,i]='
b'
;
}
else
timeB[0,i]=0;
a'
timeMax[0,i]=Math.Max(timeA[0,i],timeB[0,i]);
if(a[0]<
=b[0])
least[0]=a[0];
tempRlt[0]='
least[0]=b[0];
result[0]=newString(tempRlt);
for(intk=1;
k<
k++)
inttempSum=0;
for(inttemp=0;
temp<
=k;
temp++)
tempSum+=a[temp];
=tempSum;
{timeA[k,i]=i;
if(i<
a[k])
timeB[k,i]=timeB[k-1,i]+b[k];
who[k,i]='
else
if((timeB[k-1,i]+b[k])<
=timeB[k-1,i-a[k]])
timeB[k,i]=timeB[k-1,i-a[k]];
timeMax[k,i]=Math.Max(timeA[k,i],timeB[k,i]);
for(inti=tempSum+1;
aSum;
timeA[k,i]=tempSum;
timeB[k,i]=0;
intflag=0;
if(timeMax[k,i]>
0&
&
timeMax[k,i]<
least[k])
least[k]=timeMax[k,i];
flag=i;
tempRlt[k]=who[k,flag];
for(inti=k;
i>
flag>
0;
i--)
if(tempRlt[i]=='
)
flag-=a[i];
tempRlt[i-1]=who[i-1,flag];
result[k]=newString(tempRlt);
}
staticvoidMain(string[]args)
constintN=6;
int[]a=newint[N]{2,5,7,10,5,2};
int[]b=newint[N]{3,8,4,11,3,4};
int[]least=newint[N];
string[]result=newstring[N];
DlrwZydd(a,b,N,least,result);
Console.WriteLine();
N;
Console.WriteLine("
按要求完成前{0}项任务的机器顺序为:
+result[i]+"
时间为:
{1}"
i+1,least[i]);
实验三贪心算法
1.进一步理解算法设计的基本步骤及各步的主要内容、基本要求
2.加深对贪婪法算法设计方法的理解与应用
3.掌握将算法转化为计算机上机程序的方法
4.培养学生应用所学知识解决实际问题的能力。
1、设有n个顾客同时等待一项服务。
顾客i需要的服务时间为ti,1<
应如何安排n个顾客的服务次序才能使总的等待时间达到最小?
总的等待时间是每个顾客等待服务时间的综合。
2、一辆汽车加满油后可行驶n公里。
旅途中有若干个加油站。
设计一个有效算法,之处应在哪些加油站停靠加油,使沿途加油次数最少。
并证明算法能产生一个最优解。
(1)设计用贪婪法求解“最优服务次序问题”及“汽车加油问题”的算法;
(2)上机实现所设计的算法;
1、首先将每个顾客所需要的服务时间从小到大排序。
然后申请2个数组:
st[]是服务数组,st[j]为第j个队列上的某一个顾客的等待时间;
su[]是求和数组,su[j]的值为第j个队列上所有顾客的等待时间;
2、设加油次数为k,每个加油站间距离为a[i];
i=0,1,2,3……n
1.始点到终点的距离小于N,则加油次数k=0;
2.始点到终点的距离大于N,
①加油站间的距离相等,即a[i]=a[j]=L=N,则加油次数最少k=n;
②加油站间的距离相等,即a[i]=a[j]=L>
N,则不可能到达终点;
③加油站间的距离相等,即a[i]=a[j]=L<
N,则加油次数k=n/N(n%N==0)或k=[n/N]+1(n%N!
=0);
④加油站间的距离不相等,即a[i]!
=a[j],则加油次数k通过下面的算法求解。
最优服务次序问题:
时间复杂度为O(nlogn)
汽车加油问题:
时间复杂度为O(n)。
namespaceConsoleApplication1
{
classProgram
staticvoidMain(string[]args)
Console.Write("
请输入汽车加满油后可行驶路程:
"
);
intn=Convert.ToInt32(Console.ReadLine());
请输入途经加油站总数:
intk=Convert.ToInt32(Console.ReadLine());
int[]distance=newint[k+1];
//加油站间距
int[]note=newint[k];
//记录加油站点
Console.WriteLine("
请输入加油站间距!
i++)
{//从始点起,加油站间距
站点间距{0}:
i+1);
distance[i]=Convert.ToInt32(Console.ReadLine());
intcount;
//记录加油次数
Problemp=newProblem();
count=p.Greedy(distance,note,n);
if(count>
=0)
if(count==0)
汽车不用加油就可到达终点!
else
汽车在旅途中需加{0}次油!
count);
分别在以下加油站加了油:
note.Length;
if(note[i]!
{//输出需加油站点
第"
+note[i]+"
个加油站!
}
汽车无法到达终点!
Console.ReadKey();
classProblem
publicintGreedy(int[]d,int[]note,intn)
inti,j,s,add=0,p=0,k=d.Length;
for(i=0;
k;
if(d[i]>
n)
{//不能到达目的地
return-1;
for(j=0,s=0;
j<
j++)
s+=d[j];
if(s>
{//需要加油
add++;
note[p++]=j;
s=d[j];
returnadd;
实验四回溯法
1.掌握能用回溯法求解的问题应满足的条件;
2.加深对回溯法算法设计方法的理解与应用;
3.锻炼学生对程序跟踪调试能力;
4.通过本次实验的练习培养学生应用所学知识解决实际问题的能力。
1、设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。
设w[i][j]是从供应商j处购得的部件i的重量,c[i][j]是相应的价格。
试设计一个算法,给出总价格不超过c的最小重量机器设计。
2、设有n件工作分配给n个人。
将工作i分配给第j个人所需的费用为c[i][j]。
试设计一个算法,为每一个人都分配1件不同的工作,并使总费用达到最小。
(1)用回溯法算法设计方法求解最小重量机器设计问题和工作分配问题;
1、a.部件有n个,供应商有m个,分别用w[i][j]和c[i][j]存储从供应商j处购得的部件i的重量和相应价格,d为总价格的上限。
b.用递归函数backtrack(i)来实现回溯法搜索排列树(形式参数i表示递归深度)。
①若cp>
d,则为不可行解,剪去相应子树,返回到i-1层继续执行。
②若cw>
=sum,则不是最优解,剪去相应子树,返回到i-1层继续执行。
③若i>
n,则算法搜索到一个叶结点,用sum对最优解进行记录,返回到i-1层继续执行;
④用for循环对部件i从m个不同的供应商购得的情况进行选择(1≤j≤m)。
c.主函数调用一次Knapsack
(1)即可完成整个回溯搜索过程,最终得到的sum即为所求最小总重量。
2、a.用c[i][j]存储将工作i分配给第j个人所需的费用,用v[j]标记第j个人是否已分
配工作;
b.用递归函数backtrack(i,total)来实现回溯法搜索排列树(形式参数i表示递归深
度,n用来控制递归深度,形式参数total表示当前总费用,s表示当前最优总费用):
①若total>
=s,则不是最优解,剪去相应子树,返回到i-1层继续执行;
②若i>
n,则算法搜索到一个叶结点,用s对最优解进行记录,返回到i-1层
继续执行;
③采用for循环针对n个人对工作i进行分配(1≤j≤n):
1>
若v[j]==1,则第j个人已分配了工作,找第j+1个人进行分配;
2>
若v[j]==0,则将工作i分配给第j个人(即v[j]=1),对工作i+1调用递归函数backtrack(i+1,total+c[i][j])继续进行分配;
3>
函数backtrack(i+1,total+c[i][j])调用结束后则返回v[j]=0,将工作i对
第j+1个人进行分配;
4>
当j>
n时,for循环结束;
④当i=1时,若已测试完c[i][j]的所有可选值,外层调用就全部结束;
c.主函数调用一次backtrack(1,0)即可完成整个回溯搜索过程,最终得到的s即为
所求最小总费用。
最小重量机器设计问题:
程序中最大的循环出现在递归函数backtrack(i)中,而此函数遍历排列树的时间复杂度为O(n!
),故该算法的时间复杂度为O(n!
)。
工作分配问题:
递归函数backtrack(i,total)遍历排列树的时间复杂度为O(n!
),主函数调用递归函
数backtrack(1,0),故该算法的时间复杂度为O(n!
iostream>
#defineN1000
usingnamespacestd;
intn,m,d,cp=0,cw=0,sum=0;
intc[N][N],w[N][N];
voidbacktrack(inti){
if(i>
n){
if(cw<
sum)
sum=cw;
return;
for(intj=1;
=m;
j++){
cw+=w[i][j];
cp+=c[i][j];
sum&
cp<
=d)
backtrack(i+1);
cw-=w[i][j];
cp-=c[i][j];
intmain(){
cin>
>
n>
m>
d;
for(inti=1;
i<
=n;
i++){
j++)
c[i][j];
sum+=c[i][1];
for(intk=1;
k<
k++)
w[k][j];
backtrack
(1);
sum<
system("
pause"
return0;