算法设计期末考试(七天冲刺)

目录

递归与分治策略

一、斐波那契数列

二、集合的全排列问题

三、整数划分问题

四、循环赛日程表

五、棋盘覆盖问题


递归与分治策略

递归算法一般用于解决三类问题

(1)数据的定义是按递归定义的。

(2)问题的解法按递归算法实现,例如回溯算法。

(3)数据结构形式是按递归定义的,例如树的遍历、图的搜索。

一、斐波那契数列

F(n) = \left\{\begin{matrix} 1 (n=0,1) \\ F(n-1) +F(n-2) (n>1) \end{matrix}\right.

递归算法:

int fib(int n)
{
    if(n<=1) return 1;
    return fib(n-1)+fib(n-2);
}

 递推算法:

int fib[50];
void fibonacci(int n)
{
    fib[0] = 1;
    fib[1] = 1;
    for(int i=2;i<=n;i++)
        fib[i] = fib[i-1]+fib[i-2];
}

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int a=0,b=1,c;
	int n;
	scanf("%d",&n);
	for(int i=2;i<=n;i++)
	{
		c=a+b;
		a=b;
		b=c;	
		printf(" %d",c);
	}
	return 0;
}
5
 1 2 3 5

二、集合的全排列问题

#include<bits/stdc++.h>
using namespace std;
void Perm(int list[],int k,int m)
{
	if(k==m)
	{
		for(int i=0;i<=m;i++)
			printf("%d ",list[i]);
		printf("\n");
	}
	else
	{
		for(int j=k;j<=m;j++)
		{
			swap(list[k],list[j]);//换头1234 到 头为4 4231
			Perm(list,k+1,m);//尾部全排列
			swap(list[k],list[j]);//换回来
		}
	}
}
int main()
{
	int list[6]={1,2,3,4,5,6};
	Perm(list,0,3);
	return 0;
}
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 3 2
1 4 2 3
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 3 1
2 4 1 3
3 2 1 4
3 2 4 1
3 1 2 4
3 1 4 2
3 4 1 2
3 4 2 1
4 2 3 1
4 2 1 3
4 3 2 1
4 3 1 2
4 1 3 2
4 1 2 3

三、整数划分问题

递归公式:

f(n,m)=\left\{\begin{matrix} 1 &&(n=1,m=1) \\ f(n,n) &&(n<m) \\ 1+f(n,n-1) &&(n=m)\\ f(n,m-1)+f(n-m,m) &&(n>m>1) \end{matrix}\right.

正整数n,划分数的最大加数s不超过m

即f(6,4)最大加数不超过4,划分为4+2,4+1+1...

1)f(1,m)=1,f(1,7)=1;

      f(n,1)=1 ,f(7,1)=1;

2)f(n,m)=f(n,n) m>=n

      f(3,5)=f(3,3)划分的最大加数不超过n

3)f(n,n)=1+f(n,n-1)

      f(6,6)=1+f(6,5) 6+0,5+1....

4)   f(n,m)=f(n,m-1)+f(n-m,m)

      f(6,4)=f(6,3)+f(2,4)=f(6,3)+f(2,2)=f(6,2)+f(3,3)+f(2,2)=f(6,1)+f(5,1)+f(3,3)+f(2,2)

f(6,1)不空盘子+f(5,1)空一个+f(3,3)+f(2,2)

 6个物品放入4个盘子的情况数量=6个物品全放入3个盘子的情况数量(空一个盘子)+2个物品放入4个盘子的情况(不空)

6个物品放入3个盘子的情况数量=空一个盘子、空两个盘子、不空盘子的情况数之和

包括6个物品放入2个盘子的情况

#include <bits/stdc++.h>
using namespace std;
int split(int n,int m)
{
	if(n==1||m==1)return 1;
	else if(n<m)return split(n,n);
	else if(n==m)return split(n,n-1)+1;//空一个盘子 +不空盘子
	else return split(n,m-1)+split(n-m,m);
	
}
int main()
{
	int n,m;
	//int s;
	while(~scanf("%d%d",&n,&m))//多组数据
	printf("%d\n",split(n,m));
	
	//while(cin>>n)
	//	cout<<split(n,n)<<endl;
	//scanf("%d%d",&n,&m);
	//s=split(n,m);
	//printf("%d",s);
	return 0;
}
输入:6 4
输出:9
输入:6 3
输出:7
输入:2 2
输出:2

四、循环赛日程表

n=2^k个选手

1)每个选手必须与其他n-1个选手各赛一次

2)每个选手一天只能参赛一次

3)循环赛在n-1天结束

 

假设只有两个选手,则比赛一天结束,选手1第一天遇到选手2,同样的,选手2第一天遇到选手1。则一次为基础进行比赛日程安排,将选手分为两半,则n个选手的比赛日程安排可以由n/2个选手的比赛日程决定。递归用这种一分为二的策略对选手进行划分,直到剩下最后两个选手。

下图是8个选手的比赛日程安排,左上角和左下角的两块分别是选手1到4和5到8 前三天的比赛日程安排。据此,将左上角的数字抄到右下角,将左下角的小块数字抄到右上角,就能安排好选手后四天的日程。

for(r=1;r<n;r<<=1)//左移一位后的值赋给r 相当于*2
		for(int i=0;i<n;i+=2*r)
	{
		copy(r,r+i,0,i,r);
		copy(r,i,0,r+i,r);
	}

这段代码的意思是指:for(r=1;r<n;r<<=1) 这部分的循环控制变量 r 是用来逐步扩大复制范围的。r<<=1 表示将 r 左移一位(相当于乘以2),这样每次循环 r 都会翻倍。当 r 达到 n(即 2 的 k 次方)的一半时,循环结束。

for(int i=0;i<n;i+=2*r) 则是一个内层循环,它的目的是遍历数组 a 的每一行。i 从0开始,每次增加的是两倍的 r,直到覆盖当前子矩阵的完整宽度。这样做是为了避免重复处理已经复制过的元素,因为每次外层循环,r 都会复制到新的区域。

#include<bits/stdc++.h>
using namespace std;
const int MAX=64;
int a[MAX][MAX];
void copy(int tox,int toy,int fromx,int fromy,int r)
{
	for(int i=0;i<r;i++)
	{
		for(int j=0;j<r;j++)
		{
			a[tox+i][toy+j]=a[fromx+i][fromy+j];
		}
	}
}
void Table(int k)
{
	int i,r;
	int n=1<<k;//左移k个二进制位 十进制就是2^k
//初始化第一行
	for(int i=0;i<n;i++)
	{
		a[0][i]=i+1;
	}
	for(r=1;r<n;r<<=1)//左移一位后的值赋给r 相当于*2
		for(int i=0;i<n;i+=2*r)
	{
		copy(r,r+i,0,i,r);
		copy(r,i,0,r+i,r);
	}
} 

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

int main()
{
	int k;
	while(scanf("%d",&k)&&k)
	{
		int n=1<<k;
		Table(k);
		Out(n);
	}
	return 0;
}
输入:3
  1  2  3  4  5  6  7  8
  2  1  4  3  6  5  8  7
  3  4  1  2  7  8  5  6
  4  3  2  1  8  7  6  5
  5  6  7  8  1  2  3  4
  6  5  8  7  2  1  4  3
  7  8  5  6  3  4  1  2
  8  7  6  5  4  3  2  1

五、棋盘覆盖问题

在一个2^kⅹ2^k个方格组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为特殊方格,且称该棋盘为一特殊棋盘。显然,特殊方格出现的位置有4^k 种情况,即k>=0,有4^k 种不同的特殊棋盘。用分治策略,合理规划棋盘,使划分后的子棋盘大小相同,并且每个子棋盘均含有一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。

k=1 

10
11

k=2 

2033
2213
4115
4455

 将其划分为四个子棋盘,则四个子棋盘中只有一个子棋盘有特殊方格,为了将其他棋盘化为特殊棋盘,将一个L型骨牌覆盖在三个小棋盘的会合处,则可以将问题转换为4个较小规模的棋盘覆盖问题。

 在用L型骨牌不断覆盖没有特殊方格的子棋牌会合处的过程中,我们在不断的用新的骨牌(t++)覆盖棋盘,直到棋盘只剩一个特殊方格。

#include<bits/stdc++.h>
using namespace std;
static int tile=1;
int board[1025][1025];
void ChessBoard(int tr,int tc,int dr,int dc,int size)
{
	if(size==1)return;
	int t = tile++;
	int s = size/2;
//zuoshang
	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);	
	}
//youshang
	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);	
	}
//zuoxia
	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);	
	}
//youxia
	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);	
	}				
	
}
int main()
{
	int i,j;
	int k;
	while(cin>>k)
	{
		int size = 1<<k;
		int x,y;
		scanf("%d%d",&x,&y);
		board[x][y]=0;
		ChessBoard(0,0,x,y,size);
		for(i=0;i<size;i++)
		{
			for(j=0;j<size;j++)
			{
				printf("%d\t",board[i][j]);
			}
			printf("\n");
		}
	}
	return 0;
}
输入:
2
0 1
输出:
2       0       3       3
2       2       1       3
4       1       1       5
4       4       5       5


本博客资料、代码来源于清华大学出版社算法设计与分析,本博客仅用于个人学习,可能存在纰漏,敬请批评指正。

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法设计与分析基础C期末考试主要考察学生对算法设计和分析的理解和应用能力。考试内容主要包括以下方面。 首先,考试会考察学生对算法的基本概念的理解。学生需要了解算法的定义、特性和分类等基础知识。此外,学生还需要掌握算法的时间复杂度和空间复杂度的计算方法,能够根据算法的描述估计算法的运行时间和占用空间。 其次,考试会涉及到算法设计的方法和技巧。学生需要了解常见的算法设计思想,如递归、贪心、动态规划等,并能够应用这些思想解决实际问题。同时,学生需要具备编写和调试算法的能力,能够根据问题描述设计出正确的算法,并通过测试数据验证其正确性。 另外,考试还会考察学生对常见算法的掌握程度。比如,学生需要了解排序算法的原理和实现方法,能够分析不同排序算法的时间复杂度和稳定性,并能够根据具体问题选择合适的排序算法。此外,学生还需要了解图算法和字符串算法等常见算法的基本思想和应用领域。 最后,考试还会考察学生对算法分析的能力。学生需要能够根据算法的描述和实现代码分析算法的时间复杂度,了解最坏情况和平均情况下算法的运行时间,并能够通过实验数据验证分析结果的正确性。 综上所述,算法设计与分析基础C期末考试的主要内容包括算法基础知识、算法设计思想、常见算法掌握和算法分析能力等方面。学生需要通过学习和练习,掌握这些内容,提高自己的算法设计和分析水平,以取得良好的成绩。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值