20天集训——day11

今天是考试考搜索。我搜索只会勉强写出dfs,我看代码都可以理解,但我自己打就不太OK了。

第一题:马的遍历.有一个马,问马到达棋盘上任意一个点最少要走几步. 这题是dfs的基础题目而且在第一次上dfs的时候讲过原题。只需要根据马的移动方式进行模拟搜索就行了,用dfs的模板打。

#include<bits/stdc++.h>
using namespace std;
int n,m,fx,fy,a[500][500];
void dfs(int x,int y,int step)//x马当前所在的行,y马当前所在的列,step马所走的步数
{
 if(step==200)return ;
 else
 {
  a[x][y]=step;
 }
 if(y+1<=m&&x+2<=n&&(a[x+2][y+1]==-1||a[x+2][y+1]>step+1)) dfs(x+2,y+1,step+1);
    if(y-1>0&&x+2<=n&&(a[x+2][y-1]==-1||a[x+2][y-1]>step+1)) dfs(x+2,y-1,step+1);
    if(y+2<=m&&x+1<=n&&(a[x+1][y+2]==-1||a[x+1][y+2]>step+1)) dfs(x+1,y+2,step+1);
    if(y+2<=m&&x-1>0&&(a[x-1][y+2]==-1||a[x-1][y+2]>step+1)) dfs(x-1,y+2,step+1);
    if(y-1>0&&x-2>0&&(a[x-2][y-1]==-1||a[x-2][y-1]>step+1)) dfs(x-2,y-1,step+1);
    if(y+1<=m&&x-2>0&&(a[x-2][y+1]==-1||a[x-2][y+1]>step+1)) dfs(x-2,y+1,step+1);
    if(y-2>0&&x+1<=n&&(a[x+1][y-2]==-1||a[x+1][y-2]>step+1)) dfs(x+1,y-2,step+1);
    if(y-2>0&&x-1>0&&(a[x-1][y-2]==-1||a[x-1][y-2]>step+1)) dfs(x-1,y-2,step+1);
}
int main()
{
 cin>>n>>m>>fx>>fy;
 memset(a,-1,sizeof(a));
 dfs(fx,fy,0);
 for(int i=1;i<=n;i++)
 {
  for(int j=1;j<=m;j++)
  {
   printf("%-5d",a[i][j]);
  }
  cout<<endl;
 }
 return 0;
}

第二题:在一个N行M列的棋盘上,可以放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。枚举哪些位置可以放炮,哪些不能。

#include<bits/stdc++.h>
int n,m,ans=0;
long long f[110][110][110];
using namespace std;
int main()
{
 freopen("chess.in","r",stdin);
 freopen("chess.out","w",stdout); 
 memset(f,0,sizeof(f));
 scanf("%d%d",&n,&m);
 if(m>n) swap(n,m);
 f[0][0][m]=1;
 for(int i=1;i<=n+1;i++)//枚举
  for(int j=0;j<=m+1;j++)
   for(int k=0;k<=m+1;k++)
   {
    f[i][j][k]=f[i-1][j][k];
    if(j+1<=m)     f[i][j][k]=(f[i][j][k]+(j+1)*f[i-1][j+1][k]);
       if(k+1<=m&&j-1>=0)  f[i][j][k]=(f[i][j][k]+(k+1)*f[i-1][j-1][k+1]);
    if(j+2<=m)     f[i][j][k]=(f[i][j][k]+(j+2)*(j+1)/2*f[i-1][j+2][k]);
       if(k+2<=m&&j-2>=0) f[i][j][k]=(f[i][j][k]+(k+2)*(k+1)/2*f[i-1][j-2][k+2]);
    if(k+1<=m)     f[i][j][k]=(f[i][j][k]+j*(k+1)*f[i-1][j][k+1]);
   }
 for(int i=0;i<=m+1;i++)
  for(int j=0;j<=m+1;j++)
   ans=(ans+f[n][i][j]);
 cout<<ans<<endl;
 fclose(stdin);
 fclose(stdout);
 return 0;
}

第三题:一个地方是一个长方形,被分成了n行m列个格子,某些格子能走而有些不能 现在有人每次能走到与他相邻的上下左右四个格子(如果相邻的格子能走的话),但是不同方向的花费不一样,往上,下,左,右四个方向走一次分别需要花费1,2,3,4块钱。机器人在第x1行y1列的格子上,出口在x2行y2列的格子上,问你这个人想出去最少需要花多少钱? 我本来是想按迷宫的打法,dfs搜出路径,然后记录走该路径的所需钱数,取最小数,但不知道为什么一分也没有。我自己这道题没A,老师的写法很玄学,但大概还是暴力,但用的是bfs的模板

#include<bits/stdc++.h>
using namespace std;
int rd()
{
    int z=0,mk=1;  char ch=getchar();
 while(ch<'0'||ch>'9')
 {
    if(ch=='-')mk=-1;  ch=getchar();
 }
 while(ch>='0'&&ch<='9')
 {
    z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();
 }
 return z*mk;
}
int n,m,l1,r1,l2,r2,hd=0; 
bool a[510][510];
char s[510];
int f[510][510],q[510000];
int fx[4]={1,-1,0,0},fy[4]={0,0,1,-1},cst[4]={2,1,4,3};
bool vstd[510][510];
int gtid(int x,int y)
{
   return (x-1)*m+y-1;
}
void bfs()
{
 f[l1][r1]=0;
 q[hd=1]=gtid(l1,r1);
 for(int k=1;k<=hd;++k)
 {
  int x=q[k]/m+1,y=q[k]%m+1;
  for(int i=0;i<4;++i)
   if(a[x+fx[i]][y+fy[i]])
   {
   if(f[x][y]+cst[i]<f[x+fx[i]][y+fy[i]])
   {
    f[x+fx[i]][y+fy[i]]=f[x][y]+cst[i];
    if(!vstd[x+fx[i]][y+fy[i]])
    {
     vstd[x+fx[i]][y+fy[i]]=true;
     q[++hd]=gtid(x+fx[i],y+fy[i]);
    }
   }
   }
  vstd[x][y]=false;
 }
}
int main()
{
 freopen("robot.in","r",stdin);
 freopen("robot.out","w",stdout);
 memset(f,10,sizeof(f));
 memset(vstd,0,sizeof(vstd));
 cin>>n>>m;
 for(int i=1;i<=n;++i){
  scanf("%s",s);
  for(int j=0;j<n;++j)  a[i][j+1]=(s[j]=='.');
 }
 cin>>l1>>r1>>l2>>r2;
 bfs();
 cout<<(f[l2][r2]>9999 ? -1 : f[l2][r2])<<endl;
 return 0;
}

第四题:给一 n*n 字母方阵,内可能蕴含多个"yizhong"单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*代替,以突出显示单词。 老刘说今天是搜索专练,但老师说这题是强模拟。当时我看到这题题是都蒙的,一点思路都没有。只想到全输出*骗分。这一题就是模拟题

#include<bits/stdc++.h>
using namespace std;
string a[110],s1("yizhong"),s2("gnohziy");
int f[110][110];
int main()
{
    freopen("dcfz.in","r",stdin);
    freopen("dcfz.out","w",stdout);
    int n;
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    for(int j=0;j<=n-7;j++)
        for(int i=0;i<n;i++)
        {
            string s("");
            for(int k=j;k<=j+6;k++) s=s+a[i][k];
            if(s==s1||s==s2) for(int k=j;k<=j+6;k++) f[i][k]=1;
        }
    for(int i=0;i<=n-7;i++)
        for(int j=0;j<n;j++)
        {
            string s("");
            for(int k=i;k<=i+6;k++) s=s+a[k][j];
            if(s==s1||s==s2) for(int k=i;k<=i+6;k++) f[k][j]=1;
        }
    for(int j=0;j<=n-7;j++)
    {
        for(int i=0;i<=n-7;i++)
        {
            string s("");
            for(int k=0;k<=6;k++) s=s+a[i+k][j+k];
            if(s==s1||s==s2) for(int k=0;k<=6;k++) f[i+k][j+k]=1;
        }
        for(int i=n-1;i>=6;i--)
        {
            string s("");
            for(int k=0;k<=6;k++) s=s+a[i-k][j+k];
            if(s==s1||s==s2) for(int k=0;k<=6;k++) f[i-k][j+k]=1;
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++) if(f[i][j]) cout<<a[i][j]; else cout<<'*';
        cout<<"\n";
    }
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
int a[30]={};
int n,s,l=110000000;
void o(int x,int y)
{
 if(x>=s)
 {
  if(x-s<l) l=x-s;
  return ;
  }
 if(y>n) return ;
 o(x+a[y],y+1);
 o(x,y+1);
}
int main()
{
 cin>>n>>s;
 for(int i=1;i<=n;i++)
  cin>>a[i];
 o(0,1);
 cout<<l;
 return 0;
}



猜你喜欢

转载自blog.csdn.net/wangzhuojia/article/details/81046603