搜索dfs&bfs测试

dfs,bfs,恐怖,但不恐怖的是……三道是洛谷原题,虽然断网,但第二题我做过 哈哈哈   

———————————本来不想说废话的———————————

 

1.马的遍历 

  (horse.pas/c/cpp)

【问题描述】

有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步

【输入】

一行四个数据,棋盘的大小和马的坐标

【输出】

一个n*m的矩阵,代表马到达某个点最少要走几步(不能到达则输出-1

每行的m个数用空格隔开

【输入输出样例1】

3 3 1 1

0 3 2

3 -1 1

2 1 4

 不知道为什么scdn更新了,用着haob好不方便……

#include<bits/stdc++.h> 
using namespace std;
inline const long long read() {
    long long num=0,bj=1;char x=getchar();
    while(x<'0'||x>'9') {if(x=='-')bj=-1;x=getchar();}
    while(x>='0'&&x<='9') {num=num*10+x-'0';x=getchar();}
    return num*bj;
}
long long n,m,x1,yy,ans[410][410];
const int tx[8]={2,1,-1,-2,-2,-1,1,2},ty[8]={1,2,2,1,-1,-2,-2,-1};
struct ss
{
    int x,y;
};
ss work(int x,int y)
{
    ss temp;
    temp.x=x;
    temp.y=y;
    return temp;
}
void bfs()
{
    int i,j;
    queue<ss>q;
    q.push(work(x1,yy));
    while(!q.empty())
	{
        ss xian=q.front();
        q.pop();
        int a=xian.x,b=xian.y;
        for(i=0;i<8;i++)
            if(a+tx[i]>=1&&a+tx[i]<=n&&b+ty[i]>=1&&b+ty[i]<=m&&!ans[a+tx[i]][b+ty[i]])
                if(a+tx[i]!=x1||b+ty[i]!=yy)
				{
                    ans[a+tx[i]][b+ty[i]]=ans[a][b]+1;
                    q.push(work(a+tx[i],b+ty[i]));
                }
    }
}
int main()
{
	freopen("horse.in","r",stdin);
	freopen("horse.out","w",stdout);
	
    int i,j;
    n=read(),m=read(),x1=read(),yy=read();
    for(bfs(),i=1;i<=n;i++)
	{
        for(j=1;j<m;j++)
		{
            if(!ans[i][j]&&(i!=x1||j!=yy))
                printf("%d ",-1);
            else printf("%d ",ans[i][j]);
        }
        if(!ans[i][m]&&(i!=x1||m!=yy))printf("%d\n",-1);
        else printf("%d\n",ans[i][m]);
    }
    
	fclose(stdout);
    fclose(stdin);
    return 0;
}

注意好不要越界,用bfs搜索  

 

 二.中国象棋air

  (chess.pas/c/cpp)

【问题描述】

这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!

【输入】

一行包含两个整数N,M,之间由一个空格隔开。

【输出】

总共的方案数

答案不超过int能容纳的最大值

【输入输出样例1】

1 3

7

 

【输入输出样例2】

3 2

49

 

【数据范围】

样例说明

除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。

数据范围

30% N=1

100% N,M<=6

其实这么小的数据,暴力搜索可以过的,但因为我是做过的……所以我还是选择再打一遍区间dp

#include<bits/stdc++.h>
using namespace std;
inline const long long read() {
    long long num=0,bj=1;char x=getchar();
    while(x<'0'||x>'9') {if(x=='-')bj=-1;x=getchar();}
    while(x>='0'&&x<='9') {num=num*10+x-'0';x=getchar();}
    return num*bj;
}
long long n,m,f[1020][1020][1020],ans=0;
int i,j,k;
int main()
{
	freopen("chess.in","r",stdin);
	freopen("chess.out","w",stdout);
	
    n=read(),m=read();
    for(f[0][0][0]=1,i=1;i<=n;i++)
        for(j=0;j<=m;j++)
            for(k=0;j+k<=m;k++)
			{
                f[i][j][k]+=f[i-1][j][k];
                if(j)f[i][j][k]+=f[i-1][j-1][k]*(m-k-j+1);
                if(k)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1);
                if(j>=2)f[i][j][k]+=f[i-1][j-2][k]*(m-j-k+2)*(m-j-k+1)/2;
                if(k>=2) f[i][j][k]+=f[i-1][j+2][k-2]*(j+2)*(j+1)/2;
                if(k)f[i][j][k]+=f[i-1][j][k-1]*(m-j-k+1)*j;
            }
            
    for(i=0;i<=m;i++)for(j=0;j<=m;j++)ans+=f[n][i][j];
    printf("%d",ans);
    fclose(stdout);
    fclose(stdin);
    
    return 0;
}

3.奇怪的机器人

  (robot.pas/c/cpp)

【问题描述】

有一个奇怪的机器人,它被关在一个实验室里。

实验室是一个长方形,被分成了n行m列个格子,某些格子能走而有些不嫩

现在这个机器人每次能走到与他相邻的上下左右四个格子(如果相邻的格子能走的话),但是不同方向的花费不一样,往上,下,左,右四个方向走一次分别需要花费1,2,3,4块钱。

机器人在第x1行y1列的格子上,出口在x2行y2列的格子上,问你机器人想出去最少需要花多少钱?

【输入】

第一行两个用空格隔开的整数n和m

接下来n行,每行m个字符,表示地图

如果第i行j列个字符为’.’,表示这个地方能走,否则不能

最后一行四个用空格隔开的整数x1,y1,x2,y2

保证第x1行y1列和第x2行y2列一定是’.’ 

【输出】

一行一个整数,如果机器人能出去则为它最少需要花多少钱,否则为-1

【输入输出样例1】

4 4

....

.**.

..*.

....

3 2 3 3

11

 

【输入输出样例2】

1 3

.*.

1 1 1 3

-1

 

【数据范围】

1<=n,m<=50

这题,一开始我错了,越界+少情况……

修改以后:

#include<bits/stdc++.h>
using namespace std;
inline const long long read() {
    long long num=0,bj=1;char x=getchar();
    while(x<'0'||x>'9') {if(x=='-')bj=-1;x=getchar();}
    while(x>='0'&&x<='9') {num=num*10+x-'0';x=getchar();}
    return num*bj;
}
int fx[4]={1,-1,0,0},fy[4]={0,0,1,-1},w[4]={2,1,4,3};
char s[510];
int l1,r1,l2,r2,f[510][510],q[510000],hd=0,n,m;
bool vis[510][510],a[510][510];
int work(int x,int y){return (x-1)*m+y-1;}
void bfs()
{
	f[l1][r1]=0,hd=1;
	q[hd]=work(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]+w[i]<f[x+fx[i]][y+fy[i]])
				{
					f[x+fx[i]][y+fy[i]]=f[x][y]+w[i];
					if(!vis[x+fx[i]][y+fy[i]])
					{
						vis[x+fx[i]][y+fy[i]]=true;
						q[++hd]=work(x+fx[i],y+fy[i]);
					}
				}
			}
	  vis[x][y]=false;
	}
}
int main()
{
	freopen("robot.in","r",stdin);
	freopen("robot.out","w",stdout);
	memset(f,10,sizeof(f));
	memset(vis,0,sizeof(vis));
	n=read(),m=read();int i,j;
	for(i=1;i<=n;++i)
      for(scanf("%s",s),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;
}

4.单词方阵

  (dcfz.pas/c/cpp)

【问题描述】

给一 n×n 字母方阵,内可能蕴含多个“yizhong”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*代替,以突出显示单词。

【输入】

第一行输入一个数 n 。( 7≤n≤100)。

第二行开始输入 n×n 的字母矩阵。

【输出】

突出显示单词的 n×n 矩阵。

【输入输出样例1】

8

qyizhong

gydthkjy

nwidghji

orbzsfgz

hhgrhwth

zzzzzozo

iwdfrgng

yyyygggg

*yizhong

gy******

n*i*****

o**z****

h***h***

z****o**

i*****n*

y******g

 

【输入输出样例2】

7

aaaaaaa

aaaaaaa

aaaaaaa

aaaaaaa

aaaaaaa

aaaaaaa

aaaaaaa

*******

*******

*******

*******

*******

*******

*******

这题就不算搜索了,但也可以这么说………………………………(我在说什么?)找到y后,枚举每一个方向即可,代码量还行

#include<bits/stdc++.h> 
using namespace std;
int n,i,j,l,f[101][101],b;
char a[101][101],s[]="yizhong";
int main()
{
	freopen("dcfz.in","r",stdin);
	freopen("dcfz.out","w",stdout);
	
    for(scanf("%d\n",&n),i=1;i<=n;i++)
        scanf("%s",&a[i]);
    for (i=1;i<=n;i++)
        for(j=0;j<n;j++)
            if(a[i][j]=='y') 
			{
                if(j+6<n)b=1; 
				else b=0;
                if(j+6<n)
                for(l=1;l<=6;l++)
                    if(a[i][j+l]!=s[l]){b=0;break;}
                if(b) 
				for(l=0;l<=6;l++)f[i][j+l]=1;
                if(i+6<=n)b=1; 
				else b=0;
                if(i+6<=n)
                    for(l=1;l<=6;l++)
                        if(a[i+l][j]!=s[l]){b=0;break;}
                if(b) 
				for(l=0;l<=6;l++)f[i+l][j]=1;
                if(j-6>=0)b=1; 
				else b=0;
                if(j-6>=0)
                    for(l=1;l<=6;l++)
                        if(a[i][j-l]!=s[l]){b=0;break;}
                if(b)
				for(l=0;l<=6;l++)f[i][j-l]=1;
                if(i-6>0)b=1;
				else b=0;
                if(i-6>0)
                    for(l=1;l<=6;l++)
                        if(a[i-l][j]!=s[l]){b=0;break;}
                if(b) 
				for(l=0;l<=6;l++) 
				  f[i-l][j]=1;
                if((i-6>0)&&(j-6>=0))b=1; 
				else b=0;
                if((i-6>0)&&(j-6>=0))
                    for(l=1;l<=6;l++)
                        if(a[i-l][j-l]!=s[l]){b=0;break;}
                if(b)
				for(l=0;l<=6;l++)f[i-l][j-l]=1;
                if((i-6>0)&&(j+6<n))b=1; 
				else b=0;
                if((i-6>0)&&(j+6<n))
                    for(l=1;l<=6;l++)
                        if(a[i-l][j+l]!=s[l]){b=0;break;}
                if(b)
				for(l=0;l<=6;l++)f[i-l][j+l]=1;
                if((i+6<=n)&&(j-6>=0))b=1; 
				else b=0;
                if((i+6<=n)&&(j-6>=0))
                    for(l=1;l<=6;l++)
                        if(a[i+l][j-l]!=s[l]){b=0;break;}
                if(b)
				for(l=0;l<=6;l++)f[i+l][j-l]=1;
                if((i+6<=n)&&(j+6<n))b=1;
				else b=0;
                if((i+6<=n)&&(j+6<n))
                    for(l=1;l<=6;l++)
                        if(a[i+l][j+l]!=s[l]){b=0;break;}
                if(b)
				for(l=0;l<=6;l++)f[i+l][j+l]=1;
            }
    for(i=1;i<=n;i++)
	{
        for(j=0;j<n;j++)
            if(f[i][j])printf("%c",a[i][j]);
            else printf("*");
        printf("\n");
    }
    
    fclose(stdout);
    fclose(stdin);
    return 0;
}

谢谢观赏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值