算法分析与设计-实验一 递归与分治算法设计


一、实验目的:
掌握分治算法的基本思想,掌握分治算法的设计步骤及用递归技术实现分治策略。

二、实验所用仪器及环境
Windows 7 以上操作系统,PC机,codeblocks环境

三、 实验原理:
算法总体思想:对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之,如下图所示。

四、 实验内容:

1、棋盘覆盖问题

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

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
int chess[maxn][maxn]={0};
int gupaihao=1;///公共变量骨牌号
void chesser(int zuoshangY,int zuoshangX,int teshuY,int teshuX,int n)///n是实际大小,
{
    if(n==1)//bianjie
    {
        return ;
    }
    int t=gupaihao++;
    int dangqiankuaidaxiao=n/2;///2K,不怕出0.5
    //左上
    if(zuoshangY+dangqiankuaidaxiao>teshuY&&zuoshangX+dangqiankuaidaxiao>teshuX)
    ///有特殊方格
    {
        ///接着分
        chesser(zuoshangY,zuoshangX,teshuY,teshuX,dangqiankuaidaxiao);
    }
    else{//yao else
        ///meiyou,左上角棋盘要盖右下角
        chess[zuoshangY+dangqiankuaidaxiao-1][zuoshangX+dangqiankuaidaxiao-1]=t;
        ///剩下的这不就有了吗
        chesser(zuoshangY,zuoshangX,zuoshangY+dangqiankuaidaxiao-1,zuoshangX+dangqiankuaidaxiao-1,dangqiankuaidaxiao);///右下角成为新的特殊点
    }

    ///然后是剩下三个,一样思路

    //右上
    if(zuoshangY+dangqiankuaidaxiao>teshuY&&zuoshangX+dangqiankuaidaxiao<=teshuX)
    {
        chesser(zuoshangY,zuoshangX+dangqiankuaidaxiao,teshuY,teshuX,dangqiankuaidaxiao);
    }
    else{
        ///把左下角改喽
        chess[zuoshangY+dangqiankuaidaxiao-1][zuoshangX+dangqiankuaidaxiao]=t;
        chesser(zuoshangY,zuoshangX+dangqiankuaidaxiao,zuoshangY+dangqiankuaidaxiao-1,zuoshangX+dangqiankuaidaxiao-1,dangqiankuaidaxiao);
    }
    //zuoxia
    if(zuoshangY+dangqiankuaidaxiao<=teshuY&&teshuX<zuoshangX+dangqiankuaidaxiao)
    {
        chesser(zuoshangY+dangqiankuaidaxiao,zuoshangX,teshuY,teshuX,dangqiankuaidaxiao);
    }
    else{
        chess[zuoshangY+dangqiankuaidaxiao][zuoshangX+dangqiankuaidaxiao-1]=t;
        chesser(zuoshangY+dangqiankuaidaxiao,zuoshangX,zuoshangY+dangqiankuaidaxiao,zuoshangX+dangqiankuaidaxiao-1,dangqiankuaidaxiao);
    }

    //youxia
    if(zuoshangY+dangqiankuaidaxiao<=teshuY&&zuoshangX+dangqiankuaidaxiao<=teshuX)
    {
        chesser(zuoshangY+dangqiankuaidaxiao,zuoshangX+dangqiankuaidaxiao,teshuY,teshuX,dangqiankuaidaxiao);
    }
    else{
        chess[zuoshangY+dangqiankuaidaxiao][zuoshangX+dangqiankuaidaxiao]=t;
        chesser(zuoshangY+dangqiankuaidaxiao,zuoshangX+dangqiankuaidaxiao,zuoshangY+dangqiankuaidaxiao,zuoshangX+dangqiankuaidaxiao,dangqiankuaidaxiao);
    }
}

int main()
{
    int n;//棋盘大小
    cin>>n;
    //input 0 无 -1有
    int X,Y;
    ///横X,纵Y
    cin>>X>>Y;
   chess[X][Y]=-1;

    chesser(0,0,Y,X,n);

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            printf("%3d ",chess[i][j]);
            //cout<<chess[i][j]<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

///input
//8
//6 2

2、合并排序问题

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

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
void mergeer(int A[],int L[],int R[],int l,int r)
{
    int i=0,j=0;
    int k=0;
    while(i<l&&j<r)//首元素比较
    {
        if(L[i]<=R[j])
        {
            A[k++]=L[i++];

        }else{
        A[k++]=R[j++];
        }
    }
    ///zuoyou剩余的部分复制进来
    while(i<1)
    {
        A[k++]=L[i++];

    }
    //cout<<"#";
    while(j<r)
    {
        A[k++]=R[j++];
    }
}

void mergesort(int A[],int n)
{
    if(n>1)
    {
        int mid=n/2;
        int *left=(int *)malloc(sizeof(int)*mid);
        int *right=(int *)malloc(sizeof(int)*(n-mid));
        for(int i=0;i<mid;i++)
        {
            left[i]=A[i];
        }
        for(int i=mid;i<n;i++)
        {
            right[i-mid]=A[i];
        }

      //  cout<<"*";

        mergesort(left,mid);
        mergesort(right,n-mid);
        mergeer(A,left,right,mid,n-mid);
        free(left);
        free(right);
    }

}

int main()
{
    int a[maxn]={0};
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }

    mergesort(a,n);

    for(int i=0;i<n;i++)
    {
        cout<<a[i]<<" ";
    }


    return 0;
}
///input
//5
//2 3 6 5 1

3、集合最大元问题

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

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000

int finder(int *a,int n)
{
    if(n==1)
    {
        return a[0];
    }
    if(n==2)
        return max(a[0],a[1]);

    int mid=n/2;
    return max(finder(a,mid),finder(a+mid,n-mid));

}
int main()
{
    int n;
    cin>>n;
    int a[maxn];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    cout<<finder(a,n);
    return 0;
}
///input
//6
//2 3 5 6 4 1

4、循环赛日程表

2019年,德国甲级联赛刚刚落下帷幕。设有n支队伍参加循环赛,要求设计一个满足以下要求比赛日程表:
1)每支队伍必须与其它n-1支队伍各赛一次;
2)每支队伍一天只能赛一次。
输入:n=3
输出:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
int a[maxn][maxn]={0};
void TableCreate(int Size,int val,int x,int y)
{
    if (Size==2)
    {
        a[x][y]=val;
        a[x+1][y]=val+1;
        a[x][y+1]=val+1;
        a[x+1][y+1]=val;
        return ;
    }
    int Currentsize=Size/2;
    if(Size%2!=0)
    {
        cout<<"  WrongInput!"<<endl;
    }
    TableCreate(Currentsize,val,x,y);
    TableCreate(Currentsize,val,x+Currentsize,y+Currentsize);
    TableCreate(Currentsize,val+Currentsize,x+Currentsize,y);
    TableCreate(Currentsize,val+Currentsize,x,y+Currentsize);
}

int main()
{
    int n; //队伍数
	cin>>n;
	TableCreate(n,1,1,1);
	for(int i = 1; i <=n; i++){
		for(int j = 1; j <= n; j++){
			printf("%3d",a[i][j]);
		}
		cout<<endl;
	}

    return 0;
}

五、实验结果与分析:
通过运行程序验证程序的正确性,给出程序运行结果,分析程序出现的bug的原因,调试程序过程种出现的错误和解决方法。

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值