20天集训——day10

集训的一半已经过去,我觉得我有收获,但又没多少收获。今天是讲搜索,但其实老师并没讲什么知识点,就讲了十几二十分钟的记忆化搜索,基本上今天是在刷题的。今天我大概刷了7题搜索。好像都是深搜。

第一题:261. 细胞问题  一矩形阵列由数字0到9组成,数字1到9代表细胞数字,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。 从细胞数字开始搜,搜和它连在一起的细胞数,大于两个就是细胞了。用dfs的模板

#include<bits/stdc++.h>
using namespace std;
int n,m,l=0,s1,s2;
char a[110][110];
int fx[5]={-1,0,1,0},fy[5]={0,1,0,-1};
void dfs(int x,int y)
{
 for(int i=0;i<4;i++)
 {
  s1=x+fx[i]; s2=y+fy[i];
  if(a[s1][s2]!='0')//上下左右有没有细胞数字
  {
   a[s1][s2]='0';//避免重复搜索
   dfs(s1,s2);//继续搜索该数上下左右有没有细胞数字
  }
 }
}
int main()
{
 cin>>m>>n;
 memset(a,'0',sizeof(a));
 for(int i=1;i<=m;i++)
  for(int j=1;j<=n;j++)
   cin>>a[i][j];
 for(int i=1;i<=m;i++)
  for(int j=1;j<=n;j++)
  {
   if(a[i][j]!='0')
   {
    l++;//细胞个数
    a[i][j]='0';
    dfs(i,j);
  }
  }
 cout<<l;
 return 0;
}

第二题:给出一个5*5的矩阵,人们在矩阵中的数字中跳:向前跳、向后跳、向左跳、向右跳 (从不斜过来跳),跳到网格中的另一个数字上。他们再这样跳啊跳(按相同规 则),跳到另外一个数字上(可能是已经跳过的数字)。一共在网格内跳过五次后,他们的跳跃构建了一个六位整数。求出所有能被这样创造出来的不同整数的总数。这题依旧是暴力枚举,看能组成多少个不同的数字,用dfs来写

扫描二维码关注公众号,回复: 2165722 查看本文章

#include<bits/stdc++.h>
using namespace std;
int a[10][10]={},l=0;
bool b[1100000]={};
void h(int t)
{
 if(!b[t]) l++;
 b[t]=1;
 return ;
}
void dfs(int x,int y,int s,int k)//x是行坐标y是列坐标,s是跳的次数,k是已构建的整数

{
 if(s==6)
 {
  h(k);
  return ;
 }
 if(x+1<=5) dfs(x+1,y,s+1,k*10+a[x+1][y]);
 if(x-1>0) dfs(x-1,y,s+1,k*10+a[x-1][y]);
 if(y+1<=5) dfs(x,y+1,s+1,k*10+a[x][y+1]);
 if(y-1>0) dfs(x,y-1,s+1,k*10+a[x][y-1]);
 return ;
}
int main()
{
 for(int i=1;i<=5;i++)
  for(int j=1;j<=5;j++)
   cin>>a[i][j];
 for(int i=1;i<=5;i++)
  for(int j=1;j<=5;j++)
   dfs(i,j,1,a[i][j]);
 cout<<l;
}

第三题:给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式。暴力搜索路径并记忆化,避免路径重复。同样用dfs的模板。

#include<bits/stdc++.h>
using namespace std;
int n,m,t,q1,q2,p1,p2,b,c,s1,s2,l=0;
int f1[5]={-1,0,1,0},f2[5]={0,1,0,-1};
bool a[10][10]={};
void dfs(int x,int y)
{
 if(x==q1&&y==q2)
 {
  l++; return ;
 }
 a[x][y]=0;
 for(int i=0;i<4;i++)//向4个方向递归搜索路径
 {
  s1=x+f1[i]; s2=y+f2[i];
  if(a[s1][s2]) dfs(s1,s2);
 }
 a[x][y]=1;
}
int main()
{
 cin>>n>>m>>t;
 cin>>p1>>p2>>q1>>q2;
 for(int i=1;i<=n;i++)
  for(int j=1;j<=m;j++)
   a[i][j]=1;
 for(int i=1;i<=t;i++)
 {
  cin>>b>>c;
  a[b][c]=0;
 }
 dfs(p1,p2);
 cout<<l;
}

第四题:整数划分——之前的博客中已有。

第五题:在一个n×n的棋盘上放置n个国际象棋中的皇后,要求所有的皇后之间都不形成攻击。请你给出所有可能的排布方案数。 枚举每个皇后的位置同时将其列行标记避免与其他皇后有攻击。

#include<bits/stdc++.h>
using namespace std;
int n,l=0;
bool a[20]={},b[50]={},c[50]={};
int d[20];
void dfs(int x)
{
 if(x==n)
 {
  l++; return ;
 }
 for(int i=0;i<n;i++)
  if(!(a[i]||b[x-i+n]||c[x+i]))
  {
   a[i]=b[x-i+n]=c[x+i]=1;//记录以放皇后的攻击范围
   d[x]=i;
   dfs(x+1);
   a[i]=b[x-i+n]=c[x+i]=0;
  }
}
int main()
{
 cin>>n;
 dfs(0);
 cout<<l;
}



猜你喜欢

转载自blog.csdn.net/wangzhuojia/article/details/81032674
今日推荐