最近的一些学习
关于bfs,广度搜索。具体的情景就是老鼠走迷宫,当老鼠可以有多个方向像湖水一样四散开来的情况就可以使用广度搜索,其中求最短路的问题和dfs不共用。不然dfs可以解决一部分的bfs问题。(多了一个level的概念,四散开来的时候有同一级的概念)。
贴一个三维的bfs模板
#include<bits/stdc++.h>
using namespace std;
char map1[12][12][12];
int direction[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
int num,k,n,m;
struct node{
int x,y,z;
};
#define CHECK(x,y,z) (x<m&&x>=0&&y<n&&y>=0&&z<k&&z>=0)
void bfs(int dx,int dy, int dz){
num=1;
node start,next;
queue<node>q;
start.x=dx;
start.y=dy;
start.z=dz;
q.push(start);
while(!q.empty()){
start=q.front();
q.pop();
for(int i=0;i<6;i++){
next.x=start.x+direction[i][0];
next.y=start.y+direction[i][1];
next.z=start.z+direction[i][2];
//cout<<CHECK(next.x,next.y,next.z)<<endl;
if(CHECK(next.x,next.y,next.z)&&map1[next.z][next.y][next.x]=='.'){
map1[next.z][next.y][next.x]='#';
//cout << next.z <<next.y <<next.x <<endl;
num++;
q.push(next);
}
}
}
}
int main()
{
cin >> k >> n >> m;
for(int i=0;i<k;i++)
for(int j=0;j<n;j++)
for(int z=0;z<m;z++)
cin >> map1[i][j][z];
int sx,sy;
cin >> sy >> sx;
map1[0][sy-1][sx-1]='#';
bfs(sx-1,sy-1,0);
cout << num;
return 0;
}
基本上就是定方向,结构体表示xyz,使用stl中的queue来模拟先进先出向下荡漾开的模式。中间做好范围的确定和是否可以进入的判定就好。
dfs,深度搜索,主要以递归来实现,可以用来解决任意位置都有同样多个抉择的选择问题,可以画一个树来帮助理解。
贴一个n皇后的模板
#include<bits/stdc++.h>
using namespace std;
int n;
const int maxn=20;
char a[maxn][maxn];
bool col[maxn],dp[maxn],udp[maxn];
void dfs(int num){
if(num==n){
for(int i=0;i<n;i++){
cout << a[i];
printf("\n");
}
printf("\n");
return;
}
else{
for(int i=0;i<n;i++){
if(!col[i]&&!dp[num-i+n]&&!udp[num+i]){
a[num][i]='Q';
col[i]=dp[num-i+n]=udp[num+i]=1;
dfs(num+1);
a[num][i]='.';
col[i]=dp[num-i+n]=udp[num+i]=0;
}
}
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]='.';
dfs(0);
return 0;
}
这里有用数学知识求对角线的奇妙操作,主要注意的点就是怎么改变相关值得就需要在递归操作后全都复原不然会干扰不同分支的递归进行。
party,一道有意思的思考题,记录一下
一家公司有 n(1-2*10^3) 名员工,从 1 人到 n 人。每个员工要么没有直接经理,要么只有一个直接经理,后者是另一个具有不同编号的员工。如果以下情况中至少有一个是正确的,则称 A 雇员是 B 雇员的上级:
雇员 A 是雇员 B 的直接经理。
雇员 B 有一个直接经理雇员 C,雇员 A 是雇员 C 的上级。
公司没有管理周期。也就是说,不存在一个员工是他/她自己的直接经理的上级。
今天公司将安排一个聚会。这涉及到将所有 n 个雇员分为几个组:每个雇员必须恰好属于一个组。此外,在任何一个集团内,不得有两名雇员 A 和 B,满足 A 是 B 的上级。
必须组成的组的最小数目是多少?
题目大致如此,很难想到该以什么方式来写。一开始想的是先把每个人的所有上司放在一个数组里,然后放的时候进行比较看看有没有自己的上司在里面,没有就可以放进去,有就遍历所有组,如果遍历完还没有就开个新组。不仅难以实现而且时间复杂度应该是n的三次方。
看了看题解说这是模拟一个树,提出了一个父亲表达式概念,我觉得这个比喻无比恰当。
tree[son]=father;
可以由下层树结构得到上层树结构,然后树的同层结构是不存在上下级关系的,所以将所有同层的树结构放在一起,看一下树的深度一共有多少就可以解决问题了。本质上可以硬说和我想的把所有上司找出来的操作差不多(其实一点都不一样),可以用这个父亲表达式一直递归直到遇到son=-1的没有上司的结束条件,就可以得到这颗树的深度。
#include<bits/stdc++.h>
using namespace std;
const int N=10005;
int n,tree[N],x,M=-1;
int find(int s,int step){
if(tree[s]==-1) return step+1;
return find(tree[s],step+1);
}
int main()
{
int n;
cin >> n;
for(int i=1;i<=n;i++) scanf("%d",&tree[i]);
//cout << tree[3];
for(int i=1;i<=n;i++) M=max(M,find(i,0));
printf("%d",M);
return 0;
}
借鉴的时候默认打了从0开始,导致找了半个小时的问题,没有理解提议中儿子数列对应的父亲在哪个位置。下不为例。