一个不知名大学生,江湖人称菜狗
original author: Jacky Li
Email : 3435673055@qq.comTime of completion:2024.03.30
Last edited: 2024.03.30
目录
分治法课堂案例
第1关:二分搜索技术
任务描述
编程要求
测试说明
代码如下:
第2关:棋盘覆盖问题
任务描述
编程要求
输入格式
输出格式
第3关:合并排序
任务描述
编程要求
测试说明
代码如下:
第4关:快速排序
任务描述
编程要求
测试说明
代码如下:
第5关:线性时间选择问题
任务描述
相关知识
编程要求
测试说明
代码如下:
作者有言
分治法课堂案例
第1关:二分搜索技术
任务描述
本关任务:给定一组有序整数,用二分查找技术查找X是否在序列中,在则输出Yes,不在则输出No。 输入格式:三行,第一行一个整数n,第二行n个正整数,且有序;第三行是要查找的X 输出格式:X在序列中输出下标(0开始),不在输出-1
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
代码如下:
#include<iostream>
using namespace std;
const int N = 10000;
int BSearch(int a[], int l, int r,int x)
{
/***********Begin***************/while(l <= r)
{int mid = (l + r)/2;if(x == a[mid]) return mid;else if(x < a[mid]) r = mid - 1;else l = mid + 1;}
return -1;/***********End***************/
}
int main()
{int n,x,a[N];cin>>n; for(int i = 0; i < n; i++)cin>>a[i];cin>>x; cout<<BSearch(a,0,n-1,x);return 0;}
第2关:棋盘覆盖问题
任务描述
在一个2k×2k
个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
例如:4×4
的棋盘的一种覆盖方法为:
编写函数,输出给定k
的一种棋盘覆盖。
编程要求
根据提示,在右侧编辑器补充代码。
输入格式
输入为三个正整数: size
dr
dc
其中(size=2k,0≤k≤5),(dr,dc)
是特殊方格的位置,且0≤dr,dc≤size−1
输出格式
输出棋盘覆盖方案,特殊方格处输出-1,其他位置处同一编号的L形骨牌用同一个数字表示,数字占宽4格,右对齐。
#include<iostream>
#include<iomanip>
# define SIZE 32
using namespace std;int tile = 0;
int Board[SIZE][SIZE];
//棋盘以(tr,tc)为左上角,以size为边长,特殊方格位置在(dr,dc),ChessBoard函数用分治法
//完成它四个子棋盘覆盖
void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
/************Begin**************/if(size == 1) return ;int t = tile++, s = size/2;if(dr < tr+s && dc < tc+s) //左上角里有特殊ChessBoard(tr, tc, dr, dc, s);else{Board[tr+s-1][tc+s-1]=t;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]=t;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]=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{Board[tr+s][tc+s]=t;ChessBoard(tr+s, tc+s, tr+s, tc+s, s);}/************End**************/}
int main()
{/************Begin**************/int size,dr,dc;cin>>size>>dr>>dc;Board[dr][dc]=-1;ChessBoard(0,0,dr,dc,size);/************End**************/for (int i = 0; i < size; i++) {for (int j = 0; j < size; j++)cout << setw(4) << Board[i][j];cout << endl;}
return 0;
}
第3关:合并排序
任务描述
本关任务:用合并排序方法对数组a元素排序。 输入:两行,第一行是正整数n,第二行是n个正整数 输出:排好序的一行正整数
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
代码如下:
#include<iostream>
using namespace std;
const int N = 1000;
/*******Begin***********/
void merge(int a[], int b[], int l, int mid, int r)
{int i = l, j = mid+1, k = 0, t = 0;while(i <= mid && j <= r){if(a[i] < a[j]) b[k ++] = a[i ++];else b[k ++] = a[j ++];}while(i <= mid) b[k ++] = a[i ++];while(j <= r) b[k ++] = a[j ++];for(i = l; i <= r; i ++){a[i] = b[t++];}}
void MergeSort(int a[], int b[], int l, int r)
{if(l < r){int mid = (l+r)/2;MergeSort(a, b, l, mid);MergeSort(a, b, mid+1, r);merge(a, b, l, mid, r);}
}/*******End***********/int main( )
{int n,a[N],b[N]; cin>>n; for(int i = 0 ; i < n; i ++)cin>>a[i]; MergeSort(a,b,0,n-1);for(int i = 0 ; i < n - 1; i ++)cout<<a[i]<<" "; cout<<a[n-1];return 0;}
第4关:快速排序
任务描述
本关任务:用快速排序方法对数组a元素排序。 输入:两行,第一行是正整数n,第二行是n个正整数 输出:排好序的一行正整数
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试:
测试输入:
8
4
5
3
2
9
7
1
8
预期输出:
1
2
3
4
5
7
8
9
代码如下:
#include<iostream>
using namespace std;
const int N = 1000;/**************Begin*********/
void QuickSort(int a[], int l, int r)
{// if(l >= r) return;// int m = a[l], i = l, j = r;// while(i < j)// {// while(i < j && a[i] <= m) i ++;// while(i < j && a[j] >= m) j --;// swap(a[i], a[j]);// }// swap(m, a[i]);// QuickSort(a, l, i-1);// QuickSort(a, j+1, r);if(l >= r) return;int m = a[l], i = l, j = r;while(i < j){while(i < j && a[j] >= m) j --;a[i] = a[j];while(i < j && a[i] <= m) i ++;a[j] = a[i];}a[i] = m;QuickSort(a, l, i-1);QuickSort(a, j+1, r);
}/**************End*********/
int main( )
{int n,a[N]; cin>>n; for(int i = 0 ; i < n; i ++)cin>>a[i]; QuickSort(a,0,n-1);for(int i = 0 ; i < n - 1; i ++)cout<<a[i]<<" "; cout<<a[n-1];return 0;}
第5关:线性时间选择问题
任务描述
给定线性无序数组n
个元素和一个正整数k
,1≤k≤n
,要求在线性时间找到这n个元素的第k
小。
相关知识
- 排序求第K个元素。由于排序算法的时间复杂度都在O(nlogn),因此不满足线性时间要求。
- 借用快速排序中的划分Partition思想,选一个基准元素,将比基准元素小的放到左侧,比基准元素大的放到右侧,如果基准元素的位置是j,则比较k与j的大小:
- k==j 则基准元素刚好是第k小元素,返回
- k<j 则第k小在左侧,对左侧递归找第k小
- k>j 则第k小在右侧,对右侧递归找第j-k小
- 该方法效率取决于每次选择的基准元素,如果基准元素能将数组每次分成
ϵn
和1−ϵn
(0<ϵ<1
)两部分,则能在线性时间完成找第k小任务;如果每次选择基准元素是最大值或最小值,则退化成最坏情况,时间复杂度为O(n2)
- 问题的关键变成如何在线性时间找一个基准元素,能将数组划分成
ϵn
和1−ϵn
(0<ϵ<1
)两部分.思想如下:
- 将所有元素每5个一组,分成
n/5
组,将每组的中位数找到 - 以所有中位数的中位数做为基准元素
编程要求
完成一个冒泡排序函数:
void BubbleSort(Type a[],int p,int r)
完成根据基准元素x进行划分的函数:
int Partition(int a[],int p,int r,Type x)
完成线性时间选择数组a[p]~a[r]的第k小函数:
int Select(int a[],int p,int r,int k)
- 数组元素个数小于等于75时,直接用冒泡排序,返回第k小
- 数组元素个数大于等于75时,调用Select函数,返回第k小
测试说明
-
函数中数组的元素是整型,返回值也是整型。
-
输入的数组元素是整型,且不重复。 主函数如下:
#include<iostream>
using namespace std;
int main()
{
int a[1000]={0},n,k;
cin>>n;
for(int i = 0; i < n; i ++)
cin>>a[i];
cin>>k;
cout<<Select(a,0,n-1,k)<<endl;
return 0;
}
-
直接完成要求函数即可,输入输出由隐藏主函数完成。
代码如下:
void Swap(int &a,int &b)
{//交换函数/*********begin************/int c;c = a;a = b;b = c;/*********end************/
}int Partition(int a[],int p,int r,int x)
{//以x为基准划分函数/*********begin************/int i = p, j = r;while(i < j){while(i < j && a[i] < x) i ++;while(i < j && a[j] > x) j --;Swap(a[i], a[j]);}return i;/*********end************/
}void BubbleSort(int a[],int p,int r)
{//冒泡排序/*********begin************/for(int i = p + 1; i <= r; i ++){for(int j = p; j < r - 1; j ++){if(a[j] > a[j + 1]){swap(a[j], a[j + 1]);}}}// int i=0;// while(i<=r-p)// {// for(int j=p;j<=r-i-1;j++)// {// if(a[j]>a[j+1]) Swap(a[j],a[j+1]);// }// i++;// }/*********end************/}
int Select(int a[],int p,int r,int k)
{/*********begin************/if (r - p < 75){BubbleSort(a, p, r);return a[p + k - 1];}for (int i = 0; i <= (r - p - 4) / 5; i++){int pp = p + i * 5, rr = p + 5 * i + 4;BubbleSort(a, pp, rr);int mid = (rr - pp + 1) / 2 + pp;Swap(a[mid], a[p + i]);}int x = Select(a, p, p + (r - p - 4) / 5, (r - p - 4) / 10 + 1);int i = Partition(a, p, r, x);int len = i - p + 1;if (k <= len){return Select(a, p, i, k);}else{return Select(a, i + 1, r, k - len);}/*********end************/
}
作者有言
如果感觉博主讲的对您有用,请点个关注支持一下吧,将会对此类问题持续更新……