第四周总结

1.看了15道搜索的题。

有2道题看题解看不会:树不会,有点能理解,但是代码实现看不懂;拓扑序看不懂。

2.搜索可以和 分治思想, 暴力枚举, 数据结构 数学 知识结合起来。

技巧:1.可以反向递归:比如在选和不选这两个状态,我们可以全不选,一直搜到底,然后从后面开始进行选和不选的递归。

P1123 取数游戏

#include<bits/stdc++.h>//万能头文件 
using namespace std;
const int d[8][2]={1,0,-1,0,0,1,0,-1,1,1,-1,1,1,-1,-1,-1};//方向数组用来控制搜索时的方向 
int t,n,m,s[8][8],mark[8][8],ans,mx;
void dfs(int x,int y){//搜索函数,表示搜索点(x,y) 
	if(y==m+1){//当y到边界时,搜索下一行 
		dfs(x+1,1);
		return;
	}
	if(x==n+1){//当x到边界时,搜索结束,刷新最大值 
		mx=max(ans,mx);
		return;
	}
	
	dfs(x,y+1);// 不取此数的情况 
	
	if(mark[x][y]==0){ //取此数的情况(需保证此数周围没有取其他数,即mark[i][j]==0)
		ans+=s[x][y];
		for(int fx=0;fx<8;++fx){ //标记周围的数 
			++mark[x+d[fx][0]][y+d[fx][1]];
		}
		dfs(x,y+1);
		for(int fx=0;fx<8;++fx){ //回溯 
			--mark[x+d[fx][0]][y+d[fx][1]];
		}
		ans-=s[x][y];
	}
	
}
int main(){
	cin>>t; 
	while(t--){
		memset(s,0,sizeof(s));
		memset(mark,0,sizeof(mark));//在做每个数据前都要初始化数组 
		cin>>n>>m;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				cin>>s[i][j];
			}
		}
		mx=0;
		dfs(1,1);//从点(1,1)开始搜索 
		printf("%d\n",mx);//输出答案 
	}
	return 0;
}

转自:题解 P1123 【取数游戏】 - 绿萧 的博客 - 洛谷博客https://www.luogu.com.cn/blog/greenxiao/solution-p1123

也可以从下面递归,反向思维。P1036  选数

#include<bits/stdc++.h>
using namespace std;
char pic[2048][2048];//建图 
void huatu(int x,int y,int jie)
{
	if(jie==1)//从底层建起 
	{
		pic[x][y]='/';
		pic[x][y+1]='_';
		pic[x][y+2]='_';
		pic[x][y+3]='\\';
		pic[x-1][y+1]='/';
		pic[x-1][y+2]='\\';//'\\'里有一是个转义符号
	}
	else//不断递归,分成更小的
	{
		int m=pow(2,jie);这里每个三角形的高度随阶次减少
		huatu(x,y,jie-1);//降阶 
		huatu(x,y+m,jie-1);//分图,每次都相当于在底下画两个一样的,这里因为是从下往上,不然不好存————构造的第2步
		huatu(x-m/2,y+m/2,jie-1);//画一个倒着的在三个之间————构造的第3步,反着画一个,相当于去掉中间的
	}
}
int main()
{
	int n;
	cin>>n;
	memset(pic,' ',sizeof(pic));//全图空格 
	int m=pow(2,n);//图的层数为2的n次方 
	huatu(m,1,n);//开始画图 从下往上
	int a,b;
	for(a=1;a<=m;a++)
	{
		for(b=1;b<=m*2;b++)
			printf("%c",pic[a][b]);
		printf("\n");
	}	//输出
	printf("\n");
	return 0;
}

 题解 P1498 【南蛮图腾】 - DDF - 洛谷博客https://www.luogu.com.cn/blog/alvais7heosfather/solution-p1498

2.连通块问题:将字符转换成整形变量。用个同样大的二维数组表示是否满足条件或者用另一个状态覆盖。

3.避免出现111这种用个数组判断是否选过,321 123 213 这样用不降序原则:下次递归的时候第一个选择的数组加1.

4.图形问题找找画图的规律,找不到就试试能不能暴力刻画,不行放弃。

5.数学有关的题,从数据里面找宏观的规律,往大里想。动手写几个例子,算一算。 

6.可以从多个点进行搜索。

7.有些时候用数组判断周围有没有选过数时,可以用++;

8.不知道怎么说,就是在有向图中问有几个点时可以从其他每个点都可以到达的。我们可以用搜索从每个点遍历每个点,看最后有几个点的数组等于总点数。

9.有向图求所有路径;从第一个点开始往后减节点,每减去一个节点,该节点后面链接的点就加1,最后一个点的值就是总路径。

3.可以处理 二维平面有关的问题:染色问题地图问题,连通块问题(P1506 拯救oibh总部,从四周可以搜索)。 与选数有关的问题: 多个数的全排列, 矩阵找元素和最大,有条件的选数、如P1460 健康的荷斯坦奶牛 Healthy Holsteins,和课件上的选书,工作效率。  有向图问题:(有向图一般用二维的vector表示)。找路径的条数。

上面除了多个数的全排列和有条件的选数,全是新题型。

4.感想有两个方面:

一是对深搜的感想:

搞明白什么时候用深搜:数据范围较小,变化的状态

深搜的每个状态是什么,怎么表达:1.有个奶牛钻洞的题,有个题解是将字符换'X''O'排列顺序成二进制'1''0',用排列的’1‘’0‘ 二进制转化成的十进制整数作为状态。 2.联通块问题:每个状态就是点是不是。

深搜每个状态要怎么选择,怎么走下去,怎么递归下去:1.P1036  选数,判断子集和是不是素数,刚开始我思维固化了,用了个数组去判断子集元素有没有选,结果选重复了。避免出现111时,可以用一个数组判断时候在一次整个的选择中选过; 避免123 321 213这种时,可以递归的时候升一下选择的开始数值。2.在选数问题,选和不选可以用加一,或者不变来进行递归:dfs(t+1,i+1)和dfs(t,i+1);3.连通块问题:依照题目向周围方向延申搜索。

深搜的终止条件是什么:

深搜剪枝的例子有哪些,啥时候剪枝:1.选数问题:当剩下的所有数都加上或减去时,还不满足条件时可以剪去。2.二维平面问题:当选择的点超过范围的时候剪枝。3.有向图,求所有路径的时候,可以用一个数组在每个点存上该点往后的所有路径。

P4017 最大食物链计数

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000001;
const int mod=80112002;
queue<int> q; 
int d[maxn],in[maxn],eat[maxn],head[maxn];
int n,m,tot,ans;
struct E{
	int to,nxt;
}e[maxn];
inline void add(int u,int v)
{
	e[++tot].to=v;
	e[tot].nxt=head[u];
	head[u]=tot;
}
inline void topo()
{
	for(int i=1;i<=n;i++)
	{
		if(in[i]==0)
		{
			q.push(i);
			d[i]++;//入度为0即为最弱的一个点,所以d[i]=1;
		}
	}
	while(!q.empty())
	{
		int p=q.front();
		q.pop();
		for(int i=head[p];i;i=e[i].nxt)
		{
			int go=e[i].to;
			d[go]=(d[go]+d[p])%mod;//这句话是本题的核心
			in[go]--;
			if(in[go]==0)
			q.push(go);
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		add(a,b);
		in[b]++;
		eat[a]++;//这个是判断最猛的动物没人敢吃所以它的eat即为0,在下面有用。	
	}
	topo(); 
	for(int i=1;i<=n;i++)
	{
		if(eat[i]==0)
		ans=(ans+d[i])%mod;
	}
	cout<<ans;
}

https://luckydog--xin.blog.luogu.org/solution-p4017https://luckydog--xin.blog.luogu.org/solution-p4017

同一题可能有不同的搜索递归方式,要明确用什么递归,用什么表示状态,用什么表示结束,要不要回溯。

二是对学习状态的:感觉要干一件事,就要干一件事。

每次总结的时候才发现这周没怎么学东西,而且还忘了很多,或许当时有灵光一闪,但是现在已经忘了。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个可能的计算机专业实习的实习周记总结,共10周。请根据你的实习经历进行适当的修改和调整。 第1周: 这周我开始了我的计算机专业实习,我被分配到了开发团队,我很兴奋。我主要的任务是帮助团队开发一个新的Web应用程序,这个应用程序将帮助客户更好地管理他们的业务流程。 在这个星期,我学习了公司的开发流程和工具。我还学习了使用一些新的编程语言和工具,包括JavaScript和Git。我发现这个实习很有挑战性,但我也很享受学习新东西的过程。 第2周: 这周我开始着手进行一些实际的开发工作。我在公司的开发环境中设置了一个新的项目,我使用React编写了一个简单的用户界面。我也学会了如何使用Jest进行测试。 我的导师对我非常耐心地解释了一些编程问题,我对我的编程技能有了更深入的理解。这周我也学到了很多关于敏捷开发的知识,这对于我的工作非常有帮助。 第3周: 这周我与其他团队成员一起合作编写代码。我负责一些小任务,比如创建表单和处理表单提交。我意识到我的工作与其他团队成员的工作紧密相关,我们需要相互协作才能成功地完成项目。 我还参加了一些团队会议,了解了一些关于公司业务的信息。这使我更加了解公司的目标和工作重点,这有助于我更好地完成我的工作。 第4周: 这周,我开始对我的代码进行调试。我发现有些错误很难找,但是我学到了如何使用调试工具来帮助我找到这些错误。 我还与我的导师一起进行了一些代码审核。他们对我的代码进行了审查,提出了一些建设性的意见。这对我来说是一个很好的经验,因为我学到了如何写更好的代码。 第5周: 这周我与另外一个开发团队合作,他们负责开发后端应用程序。我负责与他们协作,确保前端和后端代码能够顺利交互。这让我更好地了解了整个应用程序的架构和流程。 我还学习了一些关于代码部署的知识,包括如何将代码部署到生产环境中。这些知识对于我未来的工作非常有帮助。 第6周: 这

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值