第五周学习总结

本周由于各种原因,看题目看博客时间大大减少了,导致了本周看的内容偏少,周六周天也尽力在弥补本周欠下的学习内容。本周同样还是看的相关搜索的内容,话不多说,在此总结一下本周所看所学到的东西。

P3884 [JLOI2009]二叉树问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
struct node{
	int father;  //爸爸
	int left;    //左儿子
	int right;   //右儿子
	int deep;    //深度
	int data;    //记录节点走过没
}a[10001];
int sum[101];
int lca(int x,int y){      //最最重要!!!求最近公共祖先
	a[x].data=1;           //把x的节点记录已走过
	while(a[x].father!=0){ //遍历至根节点
		x=a[x].father;     //更新遍历爸爸
		a[x].data=1;       //记录已走过
	}
	while(a[y].data!=1){   //遍历至x节点已走过的节点,找到最近公共祖先
		y=a[y].father;
	}
	return y;
}
int main(){
	int n,x,y,s,t,maxx=1;
	cin>>n;
	a[1].deep=1;    //根节点的深度为1
	a[1].father=0;  //根节点没有爸爸
	for(int i=1;i<n;i++){
		cin>>x>>y;
		if(a[x].left==0)    //这个节点是否有左儿子
		   a[x].left=y;     //变成左儿子
		else                //变成右儿子
		   a[x].right=y;
		a[y].father=x;
		a[y].deep=a[x].deep+1;   //更新深度
		if(a[y].deep>maxx)       //求出最大深度,第一个问题完成
		   maxx=a[y].deep;
	}
	cin>>s>>t;
	int f=lca(s,t),num=0,num1=0;
	while(s!=f){                //记录s到最近公共祖先有多少条边
		s=a[s].father;
		num++;
	}
	num*=2;   //结点间距离的定义:由结点向根方向(上行方向)时的边数×2,
	while(t!=f){               //记录t到最近公共祖先有多少条边
		t=a[t].father;
		num1++;
	}
	for(int i=1;i<=n;i++)      //把每一个深度有多少个节点记录
	    sum[a[i].deep]++;
	sort(sum+1,sum+1+100);
	cout<<maxx<<endl<<sum[100]<<endl<<num+num1; //sum[100]是最大的宽度节点个数
	return 0;
}

在此搜索题目里,用到了二叉树的知识。利用二叉树的性质进行了搜索。现在对二叉树的相关知识还不太清楚。通过这个题目,简单了解了一下二叉树的知识,但是太浅薄,还需继续阅读相关资料。

P1118 [USACO06FEB]Backward Digit Sums G/S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <bits/stdc++.h>
using namespace std;
int n,p;
int a[13];
int c[13][13];
bool b[13];//判重
void dfs(int dep,int s)
{
	if(s>p)//如果现在累加的数已经超过了给定的数,就返回
		return;
	if(dep>n)//如果已经搜完了n个数,就返回
	{
		if(s==p)//如果答案跟给定的数相等
		{
			cout<<a[1];
			for(int i=2;i<=n;i++)
				cout<<" "<<a[i];
			exit(0);//终止程序
		}
		return;//如果没有输出答案,就返回
	}
	for(int i=1;i<=n;i++)
	{
		if(b[i]==false)//如果当前这个数没有用过
		{
			b[i]=true;//标记为用过
			a[dep]=i;//保存第dep个取的数
			dfs(dep+1,s+i*c[n][dep]);
			b[i]=false;//注意这里要将状态回归
		}
	}
}
int main()
{
	cin>>n>>p;//输入
	c[1][1]=1;
	for(int i=2;i<=n;i++)
		for(int j=1;j<=i;j++)
			c[i][j]=c[i-1][j]+c[i-1][j-1];//生成杨辉三角
	dfs(1,0);
	return 0;
}

要想理解这个题,必须要知道杨辉三角的知识,杨辉三角的递推式:yhsj[i][j] = yhsj[i-1][j-1] + yhsj[i][j-1]。

连通块问题:一个矩阵选其中的一个元素,在它的周围进行判断,若它的周围连通,再进行对周围判断,直到不再连通。连通的这一片为一个连通块,通常题目判断连通块的个数,此类题目比较基本。

举一个AC的例子:P1451 求细胞数量 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意:要找到细胞块,当一个细胞块被 0包围的时候,这个就算是一个细胞块。细胞块只能是上下左右被包围 ,斜着的是无用的。同时,使用 dfs 的时候,注意判断使用的边界。ac代码:

#include <iostream>

using namespace std;
int n,m,s=0;
char a[100][100];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void dfs(int x,int y)
{

    for(int i=0;i<4;i++)
   {
    int xx=x+dx[i];
    int yy=y+dy[i];
    if(xx>=0&&yy>=0&&xx<=n&&yy<=m&&a[xx][yy]!=0)
        { a[xx][yy]=0;
        dfs(xx,yy); }
   }
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        {
        char temp;
        cin>>temp;
        a[i][j]=temp-48;
        }
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
{
        if(a[i][j]!=0)
    {
        dfs(i,j);
        a[i][j]=1;
    }
}
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
{
        if(a[i][j]!=0)
            s++;
}
       cout<<s;
       return 0;
}

在做这个题目的时候,遇到了一个问题,看它题目输入的时候都是整型,开始就定义了整型数组,写完代码觉得很对,但是按照输入样例输入,调试好多次都不对。又返回回去看题目,说是字符型,又改成了字符型数组,调试还不对。过了一会,想到字符和数字之间需要转换,改了一下输入,进行调试就正确了。做完之后,思考了一下为啥整型不行,因为输入的时候两个数之间没有分开,导致一排数都存到了一个元素里。

对于这些本周所看所学写一下感悟,上周看的大部分题目较为简单,基本上都是搜索题目中基本的问题(有相应的模板和套路)。本周所看的题目难度增大,对于题目的理解变得十分吃力,没有清晰的解题思路,导致看的题目很少。而且上周基本上都是以看为主,本周一些题目代码都是自己慢慢打出来的,进行了一下实践。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值