考试(7.14)

(学习了两天半的搜索学习,7.14号我们经历了并非搜索专题的考试)

【马的遍历】

-题目描述-

在n*m的棋盘上有一个马,马的坐标为x,y。求马跳到每一个坐标所需要的最小步数,若不能跳到该点,输出-1。

-输入格式-

一行,分别为n,m,x,y。

-输出格式-

n行,每行m个数,分别输出马到每一点的步数。

-样例数据-

input

3 3 1 1

output

0 3 2 
3 -1 1 
2 1 4

-分析-

这是一道很基础的题。因为它要求每一点的最小步数,所以我们用BFS(bfs能求出最优解)实现。

-代码-

#include<bits/stdc++.h>
using namespace std;
int n,m;//棋盘大小
int nx,ny;//马的坐标
int ans[555][555]={};//统计答案
int vis[555][555]={};//标记是否访问过
struct kk
{
	int x;
	int y;
}que[222222];//队列
int head=1,tail=0;//队首队尾指针
int fx[8]={1,1,-1,-1,2,2,-2,-2};
int fy[8]={2,-2,2,-2,1,-1,1,-1};//方向数组
void bfs()
{
	for(;head<=tail;)
	{
		int x=que[head].x;
		int y=que[head].y;//记录队首坐标
		head++;//出队
	    for(int i=0;i<=7;i++)//枚举八个方向
	     if(x+fx[i]>=1&&x+fx[i]<=n&&y+fy[i]>=1&&y+fy[i]<=m)//假如没有超出边界
	      if(vis[x+fx[i]][y+fy[i]]==0)//并且没有访问过
	      {
	     	vis[x+fx[i]][y+fy[i]]=1;//标记为访问过
	     	que[++tail]=(kk){x+fx[i],y+fy[i]};//放入队列
	     	ans[x+fx[i]][y+fy[i]]=ans[x][y]+1;//答案为上个状态的答案数+1
		  } 
	}
}
int main()
{
	freopen("horse.in","r",stdin);
	freopen("horse.out","w",stdout);
	cin>>n>>m>>nx>>ny;
	que[++tail]=(kk){nx,ny};//先将马的第一个位置放入队列
	vis[nx][ny]=1;//标记为访问过
	bfs();//宽度优先搜索
	for(int i=1;i<=n;i++)
	{
	 for(int j=1;j<=m-1;j++)//枚举每一个点
	  if(vis[i][j]==1)
	  cout<<ans[i][j]<<' ';//如果访问过,说明走的到
	  else
	  cout<<-1<<' ';
	  if(vis[i][m]==1)
	  cout<<ans[i][m]<<endl;
	  else
	  cout<<-1<<endl;
    }
    fclose(stdin);
    fclose(stdout);
	return 0;  
} 

【中国象棋】

-题目描述-

(类似于8皇后问题)在n*m的棋盘上放若干个炮(可能是0个)。求方案数(注意:炮的放置方式是同行同列放置的两个炮之间不能有其他的棋子,否则就能进行攻击)点击打开链接(我们只选取其中百分之三十,及n,m<=6的数据)。

-输入格式-

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

-输出格式-

输出所有方案数(保证数据在int范围内)

-样例数据-

input

3 2

output

49

-分析-

只要有两个炮之间还有一个炮,就会形成攻击。所以每一行每一列我们最多只能放两个炮,这样就转换成了先确定好每一列的炮的状态。等所有行的状态都已经确定好了。再判断每一列的炮会不会互相攻击(如果该列的炮大于或等于3个,就会互相攻击),如果不会,答案数就加一。

(代码以及第三题已丢失)

【单词方阵】

-题目描述-

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

-输入格式-

第一行输入一个数 n 。( 7<=n<=100 )。第二行开始输入n×n 的字母矩阵。

-输出格式-

n*n的矩阵。

-样例数据-

input

8

qyizhong

gydthkjy

nwidghji

orbzsfgz

hhgrhwth

zzzzzozo

iwdfrgng

yyyygggg

output

*yizhong 
gy****** 
n*i***** 
o**z**** 
h***h*** 
z****o** 
i*****n* 
y******g

-分析-

这是一道强模拟题。模拟8个方向。但是要注意边界。

-代码-

#include<bits/stdc++.h>
using namespace std;
int n;
char a[222][222];
char c[8]={'y','i','z','h','o','n','g'};
int ans[222][222];
int fx[9]={0,-1,1,0,0,1,1,-1,-1};
int fy[9]={0,0,0,-1,1,1,-1,1,-1};//八个方向
void check(int x,int y,int k)
{
	if(k==1)
	 if(x<7)
	  return ;
	if(k==2)
	 if(n-x+1<7)
	if(k==3)
	 if(y<7)
	  return ;
	if(k==4)
	 if(n-y+1<7)
	  return ;
	if(k==5)
	 if(n-x+1<7||n-y+1<7)
	  return ; 
	if(k==6)
	 if(n-x+1<7||y<7)
	  return ;
	if(k==7)
	 if(x<7||n-y+1<7)
	  return ;
	if(k==8)
	 if(x<7||y<7)
	  return ;//8个方向边界
	for(int i=0;i<=6;i++)
	 if(a[x+fx[k]*i][y+fy[k]*i]!=c[i])
	  return ;//假如有一个字母不符合退出
	for(int i=0;i<=6;i++)
	 ans[x+fx[k]*i][y+fy[k]*i]=1;//标记
	 return ;
}
void work(int x,int y)
{
	for(int i=1;i<=8;i++)
	 check(x,y,i);
}
int main()
{
	freopen("dcfz.in","r",stdin);
	freopen("dcfz.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++)
	  cin>>a[i][j];
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++)
	  work(i,j);//每一个点都进行查找(可以判断这个点的字母是不是‘y’再进行查找)
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		 if(ans[i][j]==1)
		  cout<<a[i][j];
		 else
		  cout<<'*';//没有标记‘*’突出
		cout<<endl;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

<小结>

第二题审题错误。仔细审题很重要,理解题目意思很重要,认真检查很重要(样例出的良心也很重要)。要搞清楚到底用dfs还是bfs。这场考试,又掌握三个技巧:1)记忆化搜索;2)方向数组;3)打表。

猜你喜欢

转载自blog.csdn.net/qq_40681184/article/details/81052581