算法实验报告1

实验一

实验名称:递归与分治算法设计

实验室名称:906

实验台号:11

学生姓名: 周唯唯

专业班级: 15-计科-1

指导教师:李艳娟

实验日期:2017-9-18

 

一、  实验目的

通过棋盘覆盖问题或合并排序问题及集合最大元问题,掌握分治算法的基本思想,掌握分治算法的设计步骤及用递归技术实现分治策略。

二、实验仪器及环境:

    PC计算机;windows XP操作系统、Visual C++6.0

二、  实验内容及结果

1、 棋盘覆盖问题

在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

#include

using namespacestd;

 

int tile = 1;//全局变量骨牌编号

intBoard[4][4];//棋盘

voidChessBoard(int tr,int tc,int dr,int dc,int size);

 

int main()

{

for(int i=0; i<4; i++)

{

          for(int j=0; j<4; j++)

          {

                  Board[i][j] = 0;

          }

}

 

ChessBoard(0,0,0,1,4);

 

for(int i=0; i<4; i++)

{

          for(int j=0; j<4; j++)

          {

                  cout<

          }

          cout<

}

}

 

/**

 * tr : 棋盘左上角的行号,tc棋盘左上角的列号

 * dr : 特殊方格左上角的行号,dc特殊方格左上角的列号

 * size :size = 2^k 棋盘规格为2^k*2^k

 */

voidChessBoard(int tr,int tc,int dr,int dc,int size)

{

if(size == 1)

{

          return;

}

int t = tile++;//L型骨牌编号

int s = size/2;//分割棋盘

 

//覆盖左上角子棋盘

if(dr

{

          ChessBoard(tr,tc,dr,dc,s);

}

else//特殊方格不在此棋盘中

{

          //用编号为t的骨牌覆盖右下角

          Board[tr+s-1][tc+s-1] = t;

          //覆盖其余方格

          ChessBoard(tr,tc,tr+s-1,tc+s-1,s);

}

 

//覆盖右上角子棋盘

if(dr=tc+s)//特殊方格在此棋盘中

{

          ChessBoard(tr,tc+s,dr,dc,s);

}

else//特殊方格不在此棋盘中

{

          //用编号为t的骨牌覆盖左下角

          Board[tr+s-1][tc+s] = t;

          //覆盖其余方格

          ChessBoard(tr,tc+s,tr+s-1,tc+s,s);

}

 

//覆盖左下角子棋盘

if(dr>=tr+s && dc

{

          ChessBoard(tr+s,tc,dr,dc,s);

}

else//特殊方格不在此棋盘中

{

          //用编号为t的骨牌覆盖右上角

          Board[tr+s][tc+s-1] = t;

          //覆盖其余方格

          ChessBoard(tr+s,tc,tr+s,tc+s-1,s);

}

 

//覆盖右下角子棋盘

if(dr>=tr+s && dc>=tc+s)//特殊方格在此棋盘中

{

          ChessBoard(tr+s,tc+s,dr,dc,s);

}

else//特殊方格不在此棋盘中

{

          //用编号为t的骨牌覆盖左上角

          Board[tr+s][tc+s] = t;

          //覆盖其余方格

          ChessBoard(tr+s,tc+s,tr+s,tc+s,s);

}

 

}

 

输入:

     4*4的矩阵 特殊位置是(0,1)

输出:如图

 2、合并排序问题

对n个元素组成的序列进行排序。

基本思想:将待排序元素分成大小大致相同的两个子集合,分别对两个集合进行排序,最终将排序好的子集合合并成所要求的排好序的集合。

#include

#include

 

void Merge(int *c ,int *d,int l,intm,int r)

{

   int i=l;

   int j=m+1;

   int k=l;

   while((i<=m)&&(j<=r))

   {

        if(c[i]<=c[j])

        {

            d[k++]=c[i++];

        }

        else

        {

            d[k++]=c[j++];

        }

   }

   int q;

   if(i

   {

 

        for(q=i;q<=m;q++)

        {

 

            d[k++]=c[q];

        }

   }

   else

   {

        for(q=j;q<=r;q++)

        {

 

            d[k++]=c[q];

        }

 

   }

}

void MergeSort(int *a,int *b,intleft,int right)

{

   if(left

   {

        int i=(left+right)/2;

        MergeSort(a,b,left,i);

        MergeSort(a,b,i+1,right);

        Merge(a,b,left,i,right);//合并到b

        int j;

        for(j=left;j<=right;j++)//每次合并一次就给a更新

        {

            a[j]=b[j];

        }

 

   }

 

}

int main()

{

    int n,i;

    printf("请输入数组元素的个数:");

    scanf("%d",&n);

    int *a=(int *)malloc(sizeof(int)*n);

    int *b=(int *)malloc(sizeof(int)*n);//临时数组

    printf("请输入要排序的数组:");

    for(i=0;i

    {

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

    }

    MergeSort(a,b,0,n-1);

    //排序后

    for(i=0;i

    {

         printf("%d ",a[i]);

    }

   return 0;

}

输入:

数组元素个数6

待排序的数组元素为:0 4 8 2 6 9

输出:

合并排序后结果为:0 2 4 6 8 9

 

 

3、集合最大元问题

在规模为n的数据元素集合中找出最大元。当n=2时,一次比较就可以找出两个数据元素的最大元和最小元。当n>2时,可以把n个数据元素分为大致相等的两半,一半有n/2个数据元素,而另一半有n/2个数据元素。 先分别找出各自组中的最大元,然后将两个最大元进行比较,就可得n个元素的最大元

#include

#include

 

int cal(int *a,int left,int right)

{

   if(left==right)

        return a[left];

   else if(left+1==right)

         returna[left]>a[right]?a[left]:a[right];

   else

   {

        intmax_left=cal(a,left,(left+right)/2);

        intmax_right=cal(a,(left+right)/2+1,right);

        returnmax_left>max_right?max_left:max_right;

 

   }

 

}

 

int main()

{

   int n;

   printf("请输入数组的个数:");

   scanf("%d",&n);

   int *a=(int*)malloc(sizeof(int)*n);

   printf("请输入原始数据:");

 

   int i;

   for(i=0;i

   {

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

   }

 

    printf("最大的数为:%d",cal(a,0,n-1));

   return 0;

}

输入:

请输入数组的个数:6

请输入原始数据:04 8 2 1 3

输出:

最大的数为:8

四、实验心得体会:(包括遇到的问题及解决办法)

1.棋盘覆盖

  注意0为初始化的矩阵值

  tile从1开始

 

 

2.合并排序:

  问题(1):一开始不知道临时数组b该在哪里声明

  解决:int *b=(int *)malloc(sizeof(int)*n);//临时数组应在调用Mergesort()之前就开辟空间,然后调用合并排序传参,这样可以节省空间。

  

问题(2):什么时候将数组复制

全部分好以后,每次合并一次就给a更新,然后再继续合并

 

3.集合最大元:

问题:动态开辟内存空间应该怎么传递参数

解决:直接将指针作为参数传递,使函数中的指针临时指向所开辟的内存

       

五、指导教师意见及成绩

 

 

                                  签名:

                                               年月日

你可能感兴趣的:(算法设计与分析)