第三轮测试卷一(2020.10.29)
试卷分析:本试卷的问题主要是:DFS还没有掌握,最小生成树和0-1背包的代码没有记住,且最小生成树不知道怎么运用到实际中去。而第5题的思路很新奇,自己需要积累。第8题自己不熟悉。
- 铺石板,输入n x m的广场,和a x a的石板,求最少需要多少石板?
/*
算法思想:没啥。。。。
理解向上取整就行
*/
num=((n+a-1)/a)*((m+a-1)/a);
-
用的0-1背包
-
找铺水管一共有多少种铺法?
//算法思想:DFS
#include<stdio.h>
#include<string>
int n,m;
char maze[105][105];
int vis[105][105];
int sum=0;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void DFS(int x,int y)
{
if(maze[x][y]=='E')
{
sum++;
return;
}
if(x<0||x>=n||y<0||y>=m)
return;
if(vis[x][y]==1)
return;
for(int i=0;i<4;i++)
{
vis[x][y]=1;
DFS(x+dx[i],y+dy[i]);
vis[x][y]=0;
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
scanf("%s",maze[i]);
memset(vis,0,sizeof(vis));//初始化
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(maze[i][j]=='S')
DFS(i,j);
}
}
printf("%d\n",sum);
return 0;
}
- 将N个村庄连接起来(可以是间接连接),求最低成本
/*
算法思想:建立最小生成树,用Prim或者克鲁斯卡尔算法
自己的问题:不知道如何使用,对于图的算法,还有数据结构形式,不是很熟悉
*/
int getRoot(int a,int set[])
{
while(a!=set[a])
a=set[a];
return a;
}
int lowcost(Road road[])//本算法返回最小花费
{
int i;
int a,b,min;
int set[100];//定义并查集
min=0;
for(i=0;i<N;i++)
set[i]=1;//初始化并查集,各村庄是孤立的,因此自己就是根节点
for(i=0;i<M;i++)
{
/*下面这个if语句将已经有道路相连的村庄合并为一个集合*/
if(road[i].is==1)
{
a=getRoot(road[i].a,set);
b=getRoot(road[i].b,set);
set[a]=b;
}
}
/*假设函数sort()已经定义,即对road[]中的M条道路按照花费进行递增排序*/
sort(road,M);
/*下面这个循环从road[]数组中逐个挑出应修的道路*/
for(i=0;i<M;i++)
{
if(road[i].is==0 && (a=getRoot(road[i].a,set)) != (b=getRoot(road[i].b,set)))
/*当a,b不属于一个集合,并且a、b间没有道路时,将a、b并入同一集合,并记录下修建a、b间道路所需的花费*/
{
set[a]=b;
min+=road[i].cost;
}
}
return min;//返回最小花费
}
- 从数组L[1…n]中找到第k小数值
/*
算法思想:在进行快速排序的过程中,每轮遍历,之后,对于枢轴元素进行判断
这种思想很新,自己要学会掌握。主要对于题目如果有要求,时间复杂度要尽可能低的时候。
*/
int kth_elem(int a[],int low,int high,int k)
{
int pivot=a[low];
int low_temp=low;//由于下面会修改low与high,在递归时又要用到它们
int high_temp=high;
while(low<high)
{
while(low<high&&a[high]>=pivot)
--high;
a[low]=a[high];
while(low<high!!a[low]<=pivot)
++low;
a[high]=a[low];
}
a[low]=pivot;
//上面即为快速排序中的划分算法
//以下就是本算法思想中所述的内容
if(low==k)//由于与K相同,直接返回pivot元素
return a[low];
else if(low>k)//在前一部分表中递归寻找
return kth_elem(a,low_temp,low-1,k);
else//在后部分表中递归寻找
return kth_elem(a,low,high_temp,k-low);
}
- 求二叉树的高度
/*
算法思想:
1、递归
2、层次遍历的时候
做题的时候问题:没有完全掌握层次遍历求高度的代码,还需要熟练一些才行
*/
//方法一:采用递归的手段来做
int Height(BiTree bt)//求二叉树bt的深度
{
int hl,hr;//hl和hr分别是左子树和右子树的深度
if(bt==NULL)
return 0;
else
{
hl=Height(bt->lch);
hr=Height(bt->rch);
if(hl>hr)
return hl+1;
else
return hr+1;
}
}
//方法二:采用层次遍历来做
int Btdepth(BiTree T)
//采用层次遍历的非递归方法求解二叉树的高度
{
if(!T)
return 0;
int front=-1,rear=-1;
int last=0,leve=0;
BiTree Q[MaxSize];
Q[++rear]=T;
BiTree p;
while(front<rear)
{
p=Q[++front];
if(p->lchild)
Q[++rear]=p->lchild;
if(p->rchild)
Q[++rear]=p->rchild;
if(front==last)
{
level++;
last=rear;
}
}
return level;
}
- 反向输出单链表
/*
算法思想:
1、头插法
2、用栈
3、递归
*/
void R_Print(Linklist L)
//从尾到头输出单链表L中每个结点的值
{
if(L->next!=NULL)
R_Print(L->next);//递归
print(L->data);
}
- 判断给定二叉树是否是二叉树排序树
/*
算法思想:对于二叉排序树来说,其中序遍历序列为一个递增有序序列。因此,对给定的二叉树进行中序遍历,若始终能保持前一个值比后一个值小,则说明该二叉树是一棵二叉排序树。
思路:
1、根据二叉排序树的性质,比左子树大,比右子树小
2、本题还可以用中序遍历,将元素都存储在一个数组中,再判断是否是递增的
*/
KeyType predt=-32767; //predt为全局变量,保存当前结点中序前驱的值,初始为infit
int JudgeBST(BiTree bt)
{
int b1,b2;
if(bt==NULL)
return 1;
else
{
bl=JudgeBST(bt->lchild);
if(b1==0||predt>=bt->data)
return 0;
predt=bt->data;
b2=JudgeBST(bt->rchild);
return b2;
}
}