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

实验目的和要求

(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;

(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。

(3)分别用蛮力法和分治法求解最近对问题;

(4)分析算法的时间性能,设计实验程序验证分析结论。

实验内容

1、给定由n个整数组成的序列(a1, a2, …, an),最大子段和问题要求该序列形如ai+…+aj   的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0。

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

实验环境

     VS2010 或VC++

实验学时

    2学时,必做实验

数据结构与算法

  1. 最大字段和:

数据结构:

存储数据序列用数组a[]表示

Lefts表示左半部分字段和

Rights表示右半部分字段和

Midsum表示新字段和

算法:分治算法

  1. 骨牌覆盖

数据结构:

棋盘用二维数组board[size][size]表示,size=2^k

特殊方格用用二维数组board[dr][dc]表示

L型骨牌:个数为(4^k-1)/3,用t表示

算法:分治算法

核心源代码

1.最大字段和:

#include<stdio.h>

int MaxSum(int a[],int left,int right){

  int sum = 0,midsum = 0,leftsum = 0,rightsum = 0;

  int center;

  int s1 = 0,s2 = 0,lefts = 0,rights = 0;

  if(left == right)

    sum = a[left];

  else{

    center = (left+right)/2;

    leftsum = MaxSum(a,left,center);

    rightsum = MaxSum(a,center+1,right);

   

    for(int i = center;i>=left;i--){

      lefts += a[i];

      if(lefts > s1)

        s1 = lefts;

    }

   

    for(int j = center + 1;j <= right;j++){

      rights +=a[j];

      if(rights > s2)

        s2 = rights;

    }

   

    midsum = s1+s2;

    if(midsum<leftsum)

      sum = leftsum;

    else

      sum = midsum;

    if(sum<rightsum)

      sum = rightsum;

  }

  return sum; 

}

int main()

{

    int a[100],n;

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

    scanf("%d",&n);

  printf("请输入序列的各数值:");

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

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

    int b = MaxSum(a,0,n-1);

  printf("%d",b);

}

2.骨牌覆盖:

#include<stdio.h>

int board[100][100];

int t=0;

void ChessBoard(int tr,int tc,int dr,int dc,int size){

  int s=0,t1;

  if(size==1)

    return;

  t1=++t;

  s=size/2;

  //左上角

  if(dr<tr+s && dc<tc+s)

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

  else{

    board[tr+s-1][tc+s-1] = t1;

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

  }

  //右上角

  if(dr<tr+s &&dc>=tc+s)

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

  else{

    board[tr+s-1][tc+s] = t1;

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

  }

  //左下角

  if(dr>=tr+s && dc<tc+s)

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

  else{

    board[tr+s][tc+s-1] = t1;

    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{

    board[tr+s][tc+s] = t1;

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

  }

}

int main(){

  int size,dr,dc;

  printf("请输入棋盘size大小(size为2的k次方):");

  scanf("%d",&size);

  printf("请输入特殊棋子的行序号:");

  scanf("%d",&dr);

  printf("请输入特殊棋子的列序号:");

  scanf("%d",&dc);

  ChessBoard(0,0,dr,dc,size);

  for(int i = 0;i<size;i++){

    for(int j = 0;j<size;j++){

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

    }

    printf("\n");

  }

  return 0;

}

力扣169:

Class Solution {

public int majorityElement(int[] nums) {

        return find_num(nums,0,nums.length-1);

    }

    int find_num(int[] nums,int left,int right){

        if(left==right)

            return nums[left];

       

        int middle = (left+right)/2;

        int lefts = find_num(nums,left,middle);

        int rights = find_num(nums,middle+1,right);

        if(lefts==rights)

            return lefts;

        else{

            int count = 0;

            for(int i = left;i<=right;i++){

                if(nums[i]==lefts)

                    count++;

                if(nums[i]==rights)

                    count--;

            }

            if(count>0)

                return lefts;

            else

             return rights;

        }    

    }

}

实验结果

1.最大字段和:

2.骨牌覆盖:

  1. 力扣169

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值