• 领导讲话
  • 自我介绍
  • 党会党课
  • 文秘知识
  • 转正申请
  • 问题清单
  • 动员大会
  • 年终总结
  • 工作总结
  • 思想汇报
  • 实践报告
  • 工作汇报
  • 心得体会
  • 研讨交流
  • 述职报告
  • 工作方案
  • 政府报告
  • 调研报告
  • 自查报告
  • 实验报告
  • 计划规划
  • 申报材料
  • 当前位置: 勤学考试网 > 公文文档 > 工作汇报 > 正文

    数据结构与算法专题实验实验报告_八皇后_背包问题求解_农夫过河.

    时间:2020-11-21 13:11:32 来源:勤学考试网 本文已影响 勤学考试网手机站

    八皇后问题

    1.问题描述

    设在初始状态下在国际象棋的棋盘上没有任何棋子(这里的棋子指皇后棋子)。然后顺序在第1行,第2行……第8行上布放棋子。在每一行中共有8个可选择的位置,但在任一时刻棋盘的合法布局都必须满足3个限制条件(1)任意两个棋子不得放在同一行(2)任意两个棋子不得放在同一列上(3)任意棋子不得放在同一正斜线和反斜线上。

    2.基本要求

    编写求解并输出此问题的一个合法布局的程序。

    3、实现提示:

    在第i行布放棋子时,从第1列到第8列逐列考察。当在第i行第j列布放棋子时,需要考察布放棋子后在行方向、列方向、正斜线和反斜线方向上的布局状态是否合法,若该棋子布放合法,再递归求解在第i+1行布放棋子;若该棋子布放不合法,移去这个棋子,恢复布放该棋子前的状态,然后再试探在第i行第j+1列布放棋子。

    4 程序代码

    #include<iostream.h>

    #include<stdio.h>

    static char Queen[8][8];

    static int a[8];

    static int b[15];

    static int c[15];

    static int QueenNum=0; //记录总的棋盘状态数

    void qu(int i); //参数i代表行

    int main()

    {

    int Line,Column;

    //棋盘初始化,空格为*,放置皇后的地方为@

    for(Line=0;Line<8;Line++)

    {

    a[Line]=0; //列标记初始化,表示无列冲突

    for(Column=0;Column<8;Column++)

    Queen[Line][Column]='*';

    }

    //主、从对角线标记初始化,表示没有冲突

    for(Line=0;Line<15;Line++)

    b[Line]=c[Line]=0;

    qu(0);

    return 0;

    }

    void qu(int i)

    {

    int Column;

    for(Column=0;Column<8;Column++)

    {

    if(a[Column]==0&&b[i-Column+7]==0&&c[i+Column]==0) //如果无冲突

    {

    Queen[i][Column]='Q'; //放皇后

    a[Column]=1; //标记,下一次该列上不能放皇后

    b[i-Column+7]=1; //标记,下一次该主对角线上不能放皇后

    c[i+Column]=1; //标记,下一次该从对角线上不能放皇后

    if(i<7) qu(i+1); //如果行还没有遍历完,进入下一行

    else //否则输出

    {

    //输出棋盘状态

    int Line,Column;

    cout<<"第"<<++QueenNum<<"种状态为:"<<endl;

    for(Line=0;Line<8;Line++)

    {

    for(Column=0;Column<8;Column++)

    cout<<Queen[Line][Column]<<" ";

    cout<<endl;

    }

    cout<<endl;

    getchar();

    }

    /*如果前次的皇后放置导致后面的放置无论如何都不能满足要求,则回溯,重置*/

    Queen[i][Column]='*';

    a[Column]=0;

    b[i-Column+7]=0;

    c[i+Column]=0;

    }

    }

    }

    5 程序结果

    题目2 背包问题的求解

    1.问题描述

    假设有一个能装入总体积为T的背包和n件体积分别为w1,w2,…wn的物品,能否从n件物品中挑选若干件恰好装满背包,即使w1+w2+…+wm=T,要求找出所有满足上述条件的解。

    例如:当T=10,各件物品的体积{1,8,4,3,5,2}时,可找到下列4组解:

    (1,4,3,2)

    (1,4,5)

    (8,2)

    (3,5,2)。

    2.实现提示

    可利用回溯法的设计思想来解决背包问题。首先,将物品排成一列,然后,顺序选取物品装入背包,若已选取第i件物品后未满,则继续选取第i+1件,若该件物品“太大”不能装入,则弃之,继续选取下一件,直至背包装满为止。

    如果在剩余的物品中找不到合适的物品以填满背包,则说明“刚刚”装入的物品“不合适”,应将它取出“弃之一边”,继续再从“它之后”的物品中选取,如此重复,直到求得满足条件的解,或者无解。

    由于回溯求解的规则是“后进先出”,自然要用到“栈”。

    进一步考虑:如果每件物品都有体积和价值,背包又有大小限制,求解背包中存放物品总价值最大的问题解---最优解或近似最优解。

    3. 题目源代码

    #define maxsize 1024

    #define null 0

    #include"stdio.h"

    #include"conio.h"

    #include"stdio.h"

    typedef struct{

    int last;

    int data[maxsize];

    }seqlist; //定义顺序表结构体

    typedef struct{

    int top;

    int sum;

    int data[maxsize];

    }seqstack; //定义栈结构体

    seqstack *init_seqstack(){

    seqstack *s;

    s=new seqstack;

    if(!s)

    {

    printf("空间不足");

    return null;

    }

    else

    {

    s->top=-1;

    s->sum=0;

    return s;

    }

    } //栈初试化

    int empty_seqstack(seqstack *s)

    {

    if (s->top==-1)

    return 1;

    else

    return 0;

    } //判断空栈

    int push_seqstack(seqlist *l,int i,seqstack *s) //入栈

    {

    if(s->top==maxsize-1)

    return 0;

    else

    {

    s->top++;

    s->data[s->top]=i; //顺序表中第i 个元素,i 入栈

    s->sum=s->sum+l->data[i]; //栈中sum加和!

    return 1;

    }

    }

    int pop_seqstack(seqlist *l,seqstack *s,int *x) //出栈

    {

    if(empty_seqstack(s))

    return 0;

    else

    {

    *x=s->data[s->top];

    s->sum=s->sum-l->data[s->data[s->top]];

    s->top--;

    return 1;

    }

    }

    seqlist *init_seqlist()

    {

    seqlist *l;

    int x=1;

    l=new seqlist;

    l->last=0;

    printf("-------------------------------------------\n请依次输入个物品的大小,输入0结束。\n-------------------------------------------\n");

    scanf("%d",&x);

    while(x!=0)

    {

    l->data[l->last]=x;

    l->last++;

    scanf("%d",&x);

    }

    return l;

    }

    /*创建数组,储存物品体积*/

    void knapsk(int n,seqlist *l)

    {

    seqstack *s;

    int flag=1;

    int i=0;

    int t;

    s=init_seqstack(); //初始化栈命名为S

    while(flag!=0)

    {

    while(i<=l->last)

    {

    push_seqstack(l,i,s);

    if(s->sum==n)

    {

    printf("-------------------------------------------\n可行的解是:");

    for(t=0;t<=s->top;t++)

    printf("%d ",l->data[s->data[t]]);

    printf("\n");

    pop_seqstack(l,s,&i);

    i++;

    }

    else

    {

    if(s->sum>n)

    {

    pop_seqstack(l,s,&i);

    i++;

    }

    else

    i++;

    }

    }

    while(i==l->last+1)

    {

    flag=pop_seqstack(l,s,&i);

    i++;

    if(flag==0)

    printf("-------------------------------------------\n执行完毕");

    }

    }

    }

    int main()

    {

    int n;

    seqlist *l;

    printf("请输入背包体积n的大小,n=?");

    scanf("%d",&n);

    l=init_seqlist();

    knapsk(n,l);

    return 1;

    }

    题目3 农夫过河问题的求解

    1.问题描述

    一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西

    全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫

    才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会

    吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而

    狼不吃白菜。请求出农夫将所有的东西运过河的方案。

    2.实现提示

    求解这个问题的简单方法是一步一步进行试探,每一步搜索所有可能的选择

    ,对前一步合适的选择后再考虑下一步的各种方案。要模拟农夫过河问题,首先

    需要对问题中的每个角色的位置进行描述。可用4位二进制数顺序分别表示农夫、

    狼、白菜和羊的位置。用0表在南岸,1表示在北岸。例如,整数5 (0101)表示农

    夫和白菜在南岸,而狼和羊在北岸。

    现在问题变成:从初始的状态二进制0000(全部在河的南岸)出发,寻找一种

    全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目

    标。总状态共16种(0000到1111),(或者看成16个顶点的有向图)可采用广度优先或深度优先的搜索策略---得到从0000到1111的安全路径。

    以广度优先为例:整数队列---逐层存放下一步可能的安全状态;Visited[16]数组标记该状态是否已访问过,若访问过,则记录前驱状态值---安全路径。

    最终的过河方案应用汉字显示出每一步的两岸状态。

    3 程序代码

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

    #define MAX 20

    int a[MAX][4]; // 0 :狼,1:羊,2:菜,3:农夫,value:0:本岸,1:对岸

    int b[MAX]; //b[]+1记录每一步农夫的什么

    char *name[] = { "空手", "带狼", "带羊", "带菜" };

    void search(int iStep)

    {

    int i;

    if (a[iStep][0] + a[iStep][1] + a[iStep][2] + a[iStep][3] == 4)

    {

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

    {

    if (a[i][3] == 0)

    {

    printf("农夫%s到对岸\n", name[b[i] + 1]);

    }

    else

    {

    printf("农夫%s回本岸\n", name[b[i] + 1]);

    }

    }

    printf("\n");

    printf("\n");

    return;

    }

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

    {

    if (memcmp(a[i], a[iStep], sizeof(a[i])) == 0) //已经找过

    {

    return;

    }

    }

    if (a[iStep][1] != a[iStep][3] && (a[iStep][2] == a[iStep][1] || a[iStep][0] == a[iStep][1])) //危险

    {

    return;

    }

    for (i = -1; i <= 2; i++)

    {

    b[iStep] = i;

    memcpy(a[iStep + 1], a[iStep], sizeof(a[iStep + 1]));

    a[iStep + 1][3] = 1 - a[iStep + 1][3]; //农夫过河

    if (i == -1) //空手回

    {

    search(iStep + 1);

    }

    else if (a[iStep][i] == a[iStep][3]) //不空手回

    {

    a[iStep + 1][i] = a[iStep + 1][3];

    search(iStep + 1);

    }

    }

    }

    int main()

    {

    search(0);

    return 0;

    }

    4 程序结果

    题目4

    教学计划编制问题

    1.问题描述

    大学的每个专业都要制定教学计划。假设任何专业都有固定的学习年

    限,每学年含两学期,每学期的时间长度和学分上限值均相等。每个专业

    开设的课程都是固定的,而且课程在开设时间的安排必须满足先修关系。

    每门课程有哪些先修课程是确定的,可以有任意多门,也可以没有。每门

    课恰好占一个学期。试在这样的前提下设计一个教学计划编制程序。

    2.基本要求

    (1)输入参数包括:学期总数,一学期的学分上限,每门课的课程号

    (固定占3位的字母数字串)、学分和直接先修课的课程号。

    (2)允许用户指定下列两种编排策略之一:一是使学生在各学期中的

    学习负担尽量均匀;二是使课程尽可能地集中在前几个学期中。

    (3)若根据给定的条件问题无解,则报告适当的信息;否则,将教学

    计划输出到用户指定的文件中。计划的表格格式自行设计。

    3、实现提示:

    可设学期总数不超过12,课程总数小于100。如果输入的先修课程号不在该专业开设的课程序列中,则作为错误处理。

    3.测试数据

    学期总数:6;学分上限:10;该专业共开设12门课,课程号从C01

    到C12,学分顺序为2,3,4,3,2,3,4,4,7,5,2,3。先修关系见

    下图。

    4,程序代码

    #include<string.h>

    #include<ctype.h> //是在调用字符函数时,在源文件中包含的头文件。

    #include<malloc.h>

    #include<limits.h> // INT_MAX等

    #include<stdio.h> // EOF(=^Z或F6),NULL

    #include<stdlib.h> // atoi()52

    #include<io.h> // eof()

    #include<math.h> // floor(),ceil(),abs()

    #include<process.h> // exit()

    #include<iostream.h> // cout,cin

    // 函数结果状态代码

    #define TRUE 1

    #define FALSE 0

    #define OK 1

    #define ERROR 0

    #define INFEASIBLE -1

    typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等

    typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE

    #define MAX_NAME 10

    /* 顶点字符串的最大长度 */

    #define MAXCLASS 100

    int Z=0;

    int X=0;

    int xqzs,q=1,xfsx;

    typedef int InfoType;

    typedef char VertexType[MAX_NAME]; // 字符串类型

    /* 图的邻接表存储表示 p163 */

    #define MAX_VERTEX_NUM 100

    typedef enum{DG,DN,UDG,UDN}GraphKind; /* {有向图,有向网,无向图,无向网} */

    typedef struct ArcNode

    {

    int adjvex; /* 该弧所指向的顶点的位置 */

    struct ArcNode *nextarc; /* 指向下一条弧的指针 */

    InfoType *info; /* 该弧相关信息的指针(网的权值指针 */

    }ArcNode; /* 表结点 */

    typedef struct

    {

    VertexType data; /* 顶点信息 */

    ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */

    }VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */

    typedef struct

    {

    AdjList vertices,verticestwo;

    int vexnum,arcnum; /* 图的当前顶点数和弧数 */

    int kind; /* 图的种类标志 */

    }ALGraph;

    /* 图的邻接表存储的基本操作 */

    int LocateVex(ALGraph G,VertexType u)

    {

    /* 初始条件: 图G存在,u和G中顶点有相同特征 */

    /* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */

    int i;

    for(i=0;i<G.vexnum;++i)

    if(strcmp(u,G.vertices[i].data)==0)

    return i;

    return -1;

    }

    Status CreateGraph(ALGraph *G)

    { /* 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图) */

    int i,j,k;

    VertexType va,vb;

    ArcNode *p;

    printf("请输入教学计划的课程数: ");

    scanf("%d",&(*G).vexnum);

    printf("请输入课程先修关系的边数: ");

    scanf("%d",&(*G).arcnum);

    printf("请输入%d个课程号(%d个字符):\n",(*G).vexnum,MAX_NAME);

    for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量(头结点) */

    {

    scanf("%s",(*G).vertices[i].data);

    (*G).vertices[i].firstarc=NULL;

    }

    printf("请输入%d个课程的学分值(%d个字符):\n",(*G).vexnum,MAX_NAME);

    for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */

    {

    scanf("%s",(*G).verticestwo[i].data);

    }

    printf("请顺序输入每条弧的弧尾和弧头(以空格作为间隔):\n");

    for(k=0;k<(*G).arcnum;++k) /* 构造表结点链表 */

    {

    scanf("%s%s",va,vb);

    i=LocateVex(*G,va);

    j=LocateVex(*G,vb);

    p=(ArcNode*)malloc(sizeof(ArcNode));

    p->adjvex=j;

    p->info=NULL;

    p->nextarc=(*G).vertices[i].firstarc; /* 插在表头 */

    (*G).vertices[i].firstarc=p;

    }

    return OK;

    }

    void Display(ALGraph G)

    {

    /* 输出图的邻接矩阵G ,即输出相关的信息(把输入进去的整理后都输出来)*/

    int i;

    ArcNode *p;

    switch(G.kind)

    {

    case DG: printf("有向图\n");

    }

    printf("%d个顶点:\n",G.vexnum);

    for(i=0;i<G.vexnum;++i)

    printf("%s ",G.vertices[i].data);

    printf("\n%d条弧(边):\n",G.arcnum);

    for(i=0;i<G.vexnum;i++)

    {

    p=G.vertices[i].firstarc;

    while(p)

    {

    printf("%s→%s ",G.vertices[i].data,G.vertices[p->adjvex].data);

    p=p->nextarc;

    }

    printf("\n");

    }

    }

    void iiiiiiFindInDegree(ALGraph G,int indegree[])

    {

    /* 求顶点的入度,算法调用 */

    int i;

    ArcNode *p;

    for(i=0;i<G.vexnum;i++)

    indegree[i]=0; /* 赋初值 */

    for(i=0;i<G.vexnum;i++)

    {

    p=G.vertices[i].firstarc;

    while(p)

    {

    indegree[p->adjvex]++;

    p=p->nextarc;

    }

    }

    }

    void FindInDegree(ALGraph G,int indegree[])

    {

    /* 求顶点的入度,算法调用 */

    int i,j;

    ArcNode *p;

    for(i=0;i<G.vexnum;i++)

    indegree[i]=0; /* 赋初值 */

    for(i=0;i<G.vexnum;i++)

    {

    for(j=0;j<G.vexnum;j++)

    {

    p=G.vertices[j].firstarc;

    while(p)

    {

    if(p->adjvex==i)

    indegree[p->adjvex]++;

    p=p->nextarc;

    }

    }

    }

    }

    typedef int SElemType; /* 栈类型 */

    /*栈的顺序存储表示 */

    #define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */

    #define STACKINCREMENT 2 /* 存储空间分配增量 */

    typedef struct SqStack

    {

    SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */

    SElemType *top; /* 栈顶指针 */

    int stacksize; /* 当前已分配的存储空间,以元素为单位 */

    }SqStack; /* 顺序栈 */

    /* 顺序栈的基本操作 p47 */

    Status InitStack(SqStack *S)

    { /* 构造一个空栈S */

    (*S).base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));

    if(!(*S).base)

    exit(OVERFLOW); /* 存储分配失败 */

    (*S).top=(*S).base;

    (*S).stacksize=STACK_INIT_SIZE;

    return OK;

    }

    Status StackEmpty(SqStack S)

    { /* 若栈S为空栈,则返回TRUE,否则返回FALSE */

    if(S.top==S.base)

    return TRUE;

    else

    return FALSE;

    }

    Status Pop(SqStack *S,SElemType *e)

    { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */

    if((*S).top==(*S).base)

    return ERROR;

    *e=*--(*S).top;

    return OK;

    }

    Status Push(SqStack *S,SElemType e)

    { /* 插入元素e为新的栈顶元素 */

    if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */

    {

    (*S).base=(SElemType *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));

    if(!(*S).base)

    exit(OVERFLOW); /* 存储分配失败 */

    (*S).top=(*S).base+(*S).stacksize;

    (*S).stacksize+=STACKINCREMENT;

    }

    *((*S).top)++=e;

    return OK;

    }

    typedef int pathone[MAXCLASS];

    typedef int pathtwo[MAXCLASS];

    //拓扑排序的算法p182

    Status TopologicalSort(ALGraph G)

    { /* 有向图G采用邻接表存储结构。若G无回路,则输出G的顶点的一个拓扑序列并返回OK, */

    /* 否则返回ERROR。

     */

    int i,k,j=0,count,indegree[MAX_VERTEX_NUM];

    SqStack S;

    pathone a;

    pathtwo b;

    ArcNode *p;

    FindInDegree(G,indegree); /* 对各顶点求入度indegree[0..vernum-1] */

    InitStack(&S); /* 初始化栈 */

    for(i=0;i<G.vexnum;++i) /* 建零入度顶点栈S */

    if(!indegree[i])

    Push(&S,i); /* 入度为0者进栈 */

    count=0; /* 对输出顶点计数 */

    while(!StackEmpty(S))

    { /* 栈不空 */

    Pop(&S,&i);

    a[i]=*G.vertices[i].data;

    b[i]=*G.verticestwo[i].data;

    printf("课程%s→学分%s ",G.vertices[i].data,G.verticestwo[i].data);

    /* 输出i号顶点并计数 */

    ++count;

    for(p=G.vertices[i].firstarc;p;p=p->nextarc)

    { /* 对i号顶点的每个邻接点的入度减1 */

    k=p->adjvex;

    if(!(--indegree[k])) /* 若入度减为0,则入栈 */

    Push(&S,k);

    }

    }

    printf("\n");

    if(count<G.vexnum)

    {printf("Error!此有向图有回路!\n");

    return ERROR;

    }

    else

    {

    printf("Right!为一个拓扑序列。\n");

    }

    while(q<=xqzs)

    {

    int C=0;

    if(X<=G.arcnum)

    {

    while(C<=xfsx)

    {

    C+=*G.verticestwo[Z].data;

    ++Z;

    }

    printf("第%d个学期应学课程:",q);

    while(X<=Z)

    {

    printf("%s ",G.vertices[X].data);

    ++X;

    }

    cout<<endl;

    q++;

    }

    else

    {

    cout<<"课程编制已经完成!"<<endl;

    return OK;

    }

    }

    return OK;

    }

    void main()

    { ALGraph f;

    printf("教学计划编制问题的求解过程:\n");

    printf("请输入学期总数:");

    scanf("%d",&xqzs);

    printf("请输入学期的学分上限:");

    scanf("%d",&xfsx);

    CreateGraph(&f); //构造图

    Display(f);

    TopologicalSort(f);

    }

    试验总结

    通过本次实验,使我认识了更多的关于数据结构的知识,也使我学到 了更多的知识,而且在做的过程中遇到了一些问题,通过与同学的讨论得到了顺利的解决,加深了同学之间的友谊!

    • 考试时间
    • 范文大全
    • 作文大全
    • 课程
    • 试题
    • 招聘
    • 文档大全

    推荐访问