算法实验报告.docx

上传人:b****9 文档编号:23422008 上传时间:2023-05-16 格式:DOCX 页数:30 大小:483.90KB
下载 相关 举报
算法实验报告.docx_第1页
第1页 / 共30页
算法实验报告.docx_第2页
第2页 / 共30页
算法实验报告.docx_第3页
第3页 / 共30页
算法实验报告.docx_第4页
第4页 / 共30页
算法实验报告.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

算法实验报告.docx

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

算法实验报告.docx

算法实验报告

中南大学

算法实验

 

班级信息安全0901

学生王树雄

学号0909090128

教师冯启龙

 

【实验内容】

1.实现求n皇后问题和子集和数问题的回溯算法。

2.用动态规划的方法实现0/1背包问题。

3.用分支限界法实现0/1背包问题。

4.用深度优化的方法遍历一个图,并判断图中是否有回路存在,如果有,请输出回路。

【实验要求】

所有的输入和输出都用文件处理。

【题目分析】

(1)N皇后问题

N×N皇后问题的求解过程就是一个试探回逆的过程

 

1、首先查找第一行的可放位置,第一行全部可以放,那么我们就先将第一个皇后放在(0,0)点。

2、再查找第二行,由于第一行的(0,0)已经放了皇后,故第二行的(1,0)和(1,1)都能放皇后了,可放的就是(1,2)和(1,3)点,在(1,2)放上皇后。

3、再查找第三行,查找所以发现第三行没有可放的位置了,回逆到第二行讲皇后放到(1,3)再查找第3行。

如果还不行,就回到第一行将第一行的皇后放人下一个可放的点,依次类推,查找N×N上的所以可放的位置,直到第一行所以位置被放完,输出结果。

4、根据上面的规律可以发现,对于一个皇后放在坐标(x,y),它的下一行位置为(x-1,y)(x,y)(x+1,y)的坐标都不能再放皇后。

我们用一个数组来存放本行能放皇后的点。

用循环来查找上面行对本行的影响,将收到影响的点置FAlSE。

代码:

#include

#include

#include

#defineN4//N皇后

typedefintChessboard[N+1][N+1];//第0号位置不用

intcount=0;

boolcheck(Chessboardcb,inti,intj){//看棋盘cb是否满足合法布局

inth,k;

intm=i+j,n=i-j;

for(h=1;h

if(cb[h][j]==1&&h!

=i)returnfalse;//检查第j列

if(m-h<=N&&cb[h][m-h]==1&&h!

=i)returnfalse;//检查斜的,m-h<=N是为了保证不越界

if(h-n<=N&&cb[h][h-n]==1&&h!

=i)returnfalse;//检查斜的,h-n<=N是为了保证不越界

}

for(k=1;k

=j)returnfalse;

returntrue;

}

 

voidprintfChessboard(Chessboardcb){//打印棋盘

inti,j;

FILE*stream=fopen("a.txt","a");

fprintf(stream,"%s%d%s","(",count,")");

fputs("\n",stream);

for(i=1;i<=N;i++){

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

printf("%d",cb[i][j]);

fprintf(stream,"%d",cb[i][j]);

}

fputs("\n",stream);

printf("\n");

}

fputs("\n",stream);

fclose(stream);

printf("\n");

}

/*进入本函数时,在n*n棋盘前n-1行已放置了互不攻击的i-1个棋子。

现从第i行起继续为后续棋子选择合适位置。

当i>n时,求得一个合法的布局,输入之。

*/

voidtrial(inti,Chessboard&cb){

intj;

if(i>N){

count++;

printfChessboard(cb);

}

else{

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

cb[i][j]=1;

if(check(cb,i,j))trial(i+1,cb);

cb[i][j]=0;

}

}

}

intmain(){

inti,j;

Chessboardcb;

for(i=1;i<=N;i++)for(j=1;j<=N;j++)cb[i][j]=0;//必须初始化,它的默认值不是0

trial(1,cb);

system("pause");

return0;

}

 

(效果图)

当为4个皇后的时候

当为5个皇后的时候

子集和数问题

#include

#include

#defineM31

#defineN4//集合元素个数

intw[N]={13,11,24,7};

intx[N];

voidSubset(ints,intk)//解子集和数问题函数

{

inti,l;l=0;x[l]=k;

while(l>=0)

{

while(s+w[x[l]-1]

{

s=s+w[x[l]-1];

k++;l++;

x[l]=k;

}

while(s+w[x[l]-1]>M&&k<=N)

{

k++;x[l]=k;

}

if(s+w[x[l]-1]==M)

{k++;

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

printf("%d",x[i]);//输出变长解向量

printf("\n");

}

while(k>N)//返回上一个节点,实现回溯的主要思想

{

l--;k=x[l];x[l]=k+1;s=0;

for(i=0;i

{

s=s+w[x[i]-1];

}

}

}

}

思想也是用到回溯法。

 

intmain()

{

printf("数字代表组成结果所在的元素位置\n");

Subset(0,1);//调用subset(ints,intk)函数

system("pause");

return0;

}

 

运行效果:

(2)动态规划0/1背包

这是最基础的背包问题,特点是:

每种物品仅有一件,可以选择放或不放。

用子问题定义状态:

即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。

则其状态转移方程便是:

f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}

这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。

所以有必要将它详细解释一下:

“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。

如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

#include

#include

#defineN50

intmain()

{

intp[N],w[N],m[N][5*N];

inti,j,c,cw,n,sw,sp;

printf("请输入元素个数n:

\n");

scanf("%d",&n);

printf("请输入背包容量c:

\n");

scanf("%d",&c);

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

{

printf("输入第%d个元素的重量和价值:

\n",i);

scanf("%d",&w[i]);

scanf("%d",&p[i]);

}

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

if(j>=w[n])

m[n][j]=p[n];

else

m[n][j]=0;

for(i=n-1;i>=1;i--)

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

if(j>=w[i]&&m[i+1][j]

m[i][j]=m[i+1][j-w[i]]+p[i];

else

m[i][j]=m[i+1][j];

cw=c;

printf("\n");

printf("\n");

 

printf("背包所装物品:

\n");

printf("iW[i]p[i]\n");

for(sp=0,sw=0,i=1;i<=n-1;i++)

if(m[i][cw]>m[i+1][cw])

{

cw-=w[i];sw+=w[i];sp+=p[i];

printf("%2d%3d%3d\n",i,w[i],p[i]);

}

if(m[1][c]-sp==p[n])

{

sw+=w[i];sp+=p[i];

printf("%2d%3d%3d\n",n,w[n],p[n]);

}

printf("w=%d,pmax=%d\n",sw,sp);

printf("\n");

printf("\n");

system("pause");

return0;

}

 

#include

#include

#defineMAXNUM100

structnode{

intstep;

doubleprice;

doubleweight;

doublemax,min;

unsignedlongpo;

};

typedefstructnodeDataType;

structSeqQueue{/*顺序队列类型定义*/

intf,r;

DataTypeq[MAXNUM];

};

typedefstructSeqQueue*PSeqQueue;

PSeqQueuecreateEmptyQueue_seq(void){

PSeqQueuepaqu;

paqu=(PSeqQueue)malloc(sizeof(structSeqQueue));

if(paqu==NULL)

printf("Outofspace!

!

\n");

else

paqu->f=paqu->r=0;

returnpaqu;

}

intisEmptyQueue_seq(PSeqQueuepaqu){

returnpaqu->f==paqu->r;

}

voidenQueue_seq(PSeqQueuepaqu,DataTypex){

if((paqu->r+1)%MAXNUM==paqu->f)

printf("Fullqueue.\n");

else{

paqu->q[paqu->r]=x;

paqu->r=(paqu->r+1)%MAXNUM;

}

}

分支界限法背包

 

/*删除队列头元素*/

voiddeQueue_seq(PSeqQueuepaqu){

if(paqu->f==paqu->r)

printf("EmptyQueue.\n");

else

paqu->f=(paqu->f+1)%MAXNUM;

}

/*对非空队列,求队列头部元素*/

DataTypefrontQueue_seq(PSeqQueuepaqu){

return(paqu->q[paqu->f]);

}

/*物品按性价比从新排序*/

voidsort(intn,doublep[],doublew[]){

inti,j;

for(i=0;i

for(j=i;j

doublea=p[j]/w[j];

doubleb=p[j+1]/w[j+1];

if(a

doubletemp=p[j];

p[j]=p[j+1];

p[j+1]=temp;

temp=w[j];

w[j]=w[j+1];

w[j+1]=temp;

}

}

}

/*求最大可能值*/

doubleup(intk,doublem,intn,doublep[],doublew[]){

inti=k;

doubles=0;

while(i

m-=w[i];

s+=p[i];if(i0){

s+=p[i]*m/w[i];

i++;

}

returns;

}

/*求最小可能值*/

doubledown(intk,doublem,intn,doublep[],doublew[]){

inti=k;

doubles=0;

while(i

m-=w[i];

s+=p[i];

i++;

}

returns;

}

/*用队列实现分支定界算法*/

doublesolve(doublem,intn,doublep[],doublew[],unsignedlong*po){

doublemin;

PSeqQueueq=createEmptyQueue_seq();

DataTypex={0,0,0,0,0,0};

sort(n,p,w);

x.max=up(0,m,n,p,w);

x.min=min=down(0,m,n,p,w);

if(min==0)return-1;

enQueue_seq(q,x);

while(!

isEmptyQueue_seq(q)){

intstep;

DataTypey;

x=frontQueue_seq(q);

deQueue_seq(q);

if(x.max

step=x.step+1;

if(step==n+1)continue;

y.max=x.price+up(step,m-x.weight,n,p,w);

if(y.max>=min){

y.min=x.price+down(step,m-x.weight,n,p,w);

y.price=x.price;

y.weight=x.weight;

y.step=step;

y.po=x.po<<1;

if(y.min>=min){

min=y.min;

if(step==n)*po=y.po;

}

enQueue_seq(q,y);

}

if(x.weight+w[step-1]<=m){

y.max=x.price+p[step-1]+

up(step,m-x.weight-w[step-1],n,p,w);

if(y.max>=min){

y.min=x.price+p[step-1]+

down(step,m-x.weight-w[step-1],n,p,w);

y.price=x.price+p[step-1];

y.weight=x.weight+w[step-1];

y.step=step;

y.po=(x.po<<1)+1;

if(y.min>=min){

min=y.min;

if(step==n)*po=y.po;

}

enQueue_seq(q,y);

}

}

}

returnmin;

}

#definen4

doublem=15;

doublep[n]={10,10,12,18};

doublew[n]={2,4,6,9};

intmain(){

inti;

doubled;

unsignedlongpo;

d=solve(m,n,p,w,&po);

if(d==-1)

printf("Nosolution!

\n");

else{

for(i=0;i

printf("x%dis%d\n",i+1,((po&(1<<(n-i-1)))!

=0));

printf("Themaxweightis%f\n",d);

}

getchar();

system("pause");

return0;

}

 

i++;

}

if(i0){

s+=p[i]*m/w[i];

i++;

}

returns;

}

/*求最小可能值*/

doubledown(intk,doublem,intn,doublep[],doublew[]){

inti=k;

doubles=0;

while(i

m-=w[i];

s+=p[i];

i++;

}

returns;

}

/*用队列实现分支定界算法*/

doublesolve(doublem,intn,doublep[],doublew[],unsignedlong*po){

doublemin;

PSeqQueueq=createEmptyQueue_seq();

DataTypex={0,0,0,0,0,0};

sort(n,p,w);

x.max=up(0,m,n,p,w);

x.min=min=down(0,m,n,p,w);

if(min==0)return-1;

enQueue_seq(q,x);

while(!

isEmptyQueue_seq(q)){

intstep;

DataTypey;

x=frontQueue_seq(q);

deQueue_seq(q);

if(x.max

step=x.step+1;

if(step==n+1)continue;

y.max=x.price+up(step,m-x.weight,n,p,w);

if(y.max>=min){

y.min=x.price+down(step,m-x.weight,n,p,w);

y.price=x.price;

 

y.weight=x.weight;

y.step=step;

y.po=x.po<<1;

if(y.min>=min){

min=y.min;

if(step==n)*po=y.po;

}

enQueue_seq(q,y);

}

if(x.weight+w[step-1]<=m){

y.max=x.price+p[step-1]+

up(step,m-x.weight-w[step-1],n,p,w);

if(y.max>=min){

y.min=x.price+p[step-1]+

down(step,m-x.weight-w[step-1],n,p,w);

y.price=x.price+p[step-1];

y.weight=x.weight+w[step-1];

y.step=step;

y.po=(x.po<<1)+1;

if(y.min>=min){

min=y.min;

if(step==n)*po=y.po;

}

enQueue_seq(q,y);

}}}

returnmin;

}

#definen4

doublem=15;

doublep[n]={10,10,12,18};

doublew[n]={2,4,6,9};

intmain(){

inti;

doubled;

unsignedlongpo;

d=solve(m,n,p,w,&po);

if(d==-1)

printf("Nosolution!

\n");

else{

for(i=0;i

printf("x%dis%d\n",i+1,((po&(1<<(n-i-1)))!

=0));

printf("Themaxweightis%f\n",d);

}

getchar();

system("pause");

return0;

}

 

实验效果:

1代表该元素被用到,0代表没有用到

(3)深度优先遍历图

从图中某个顶点V0出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到,若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

  当以邻接表作存储结构时,深度优先搜索遍历图的时间复杂度为O(n+e)。

#include

#include

#include

#defineMaxVetexNum10

#defineSTACKINITSIZE30

typedefstruct{

int*base;

int*top;

intstacksize;

}SqStack;

typedefstructArcell{

int

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

当前位置:首页 > 初中教育 > 学科竞赛

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

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