HNUCM 2022年暑假ACM搜索专项练习

目录

 您好中国

 简单迷宫题

 小B旅游


 您好中国

题目描述

小明一天突发奇想,随机生成了一个全部由大写字母组成的方阵。他惊奇地发现这个方阵中包含中国的英文单词“CHINA”。
他希望你能够编写一个程序,能够找出一个由大写字母组成的方阵中所有不同的“CHINA”,要“CHINA”求中五个字母要连续出现,方向可以是上、下、左、右中的任意一个。
例如在下面的4*4的方阵中就包含了两个不同的“CHINA”。一个是第1行第1列到第3列的“CHI”,加上第2行第3列的“N”以及第2行第2列的“A”组成的“CHINA”;还有一个是第1行第1列到第3列的“CHI”,加上第2行第3列的“N”以及第3行第3列的“A”。
CHIA
CANT
GRAC
BBDE

输入

单组输入,每个测试样例包含N+1行。
第1行为方阵的大小N(N<=30)。
第2行到第N+1行用于存储由大写字母组成的方阵,每一行包含N个大写字母。

输出

输出方阵中包含的不同的CHINA的个数。如果一个都没有找到,则输出0。

样例输入 Copy

4
CHIA
CANT
GRAC
BBDE
样例输出 Copy

2
唯一值得注意的就是从字符为‘C’的位置开始dfs,其他的没啥

#include<iostream>
#include<string>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<string.h>
#include<queue> 
using namespace std;
int n,cnt;
char c[31][31];
string str="CHINA";
int vis[35][35];
void dfs(int x,int y,int t){
	if(x<0||x>=n||y<0||y>=n)return;
	if(t>=5){
		cnt++;
		return ;
	}
	if(c[x+1][y]==str[t]){
		vis[x+1][y]=1;
		dfs(x+1,y,t+1);
		vis[x+1][y]=0;
	}
	
	if(c[x-1][y]==str[t]){
		vis[x-1][y]=1;
		dfs(x-1,y,t+1);
		vis[x-1][y]=0;
	}
	
	if(c[x][y+1]==str[t]){
		vis[x][y+1]=1;
		dfs(x,y+1,t+1);
		vis[x][y+1]=0;
	}
	if(c[x][y-1]==str[t]){
		vis[x][y-1]=1;
		dfs(x,y-1,t+1);
		vis[x][y-1]=0;
	}
}
int main(){
	
	cin>>n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cin>>c[i][j];
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(c[i][j]=='C'){//从开始位置为C开始dfs
				vis[i][j]=1;
				dfs(i,j,1);
				vis[i][j]=0;
			}
		}
	}
	
	cout<<cnt<<endl;
} 

 简单迷宫题

题目描述

众多单机小游戏中都有王子救公主的情节,小波也脑补了一个迷宫游戏。现有一大小为n*m二维迷宫,告诉你王子和公主的位置,小波觉得没有点实力是不配当王子的,于是王子每次可以向他的八个方向走一步(即:上、下、左、右、左上、左下、右上、右下)。迷宫中存在一些墙壁(用'#'表示),同时还存在一些陷阱(用'*'表示,在这个游戏中,保证王子能够快速的发现陷阱并绕开,具体见样例),正常可以行走的路用'.'表示,王子的位置用'S'表示,公主的位置用'E'表示。现问你王子有多少条路可以营救公主(当然王子足够聪明,不会回头路)。

输入

第一行,迷宫的大小n、m(n,m<=100)。

接下来输入整个地图。

输出

一行,表示王子有多少种路线可以营救公主。

样例输入 Copy

3 3
*.S
*..
*E#

样例输出 Copy

10
#include <bits/stdc++.h>
using namespace std;
char c[105][105];
int vis[105][105];
int dx,dy,cnt,n,m;
int dirx[]={-1,1,0,0,-1,-1,1,1};//在x轴方向上的移动,配合diry使用
int diry[]={0,0,-1,1,-1,1,1,-1};//在y轴上的方向移动
void dfs(int x,int y){
	if(x<0||x>=n||y<0||y>=m)return;//溢出直接返回
	if(x==dx&&y==dy){//当前点为公主所在点时方案数加1
		cnt++;
		return;
	}
	for(int i=0;i<=7;i++){//8个方向遍历
		if(c[x+dirx[i]][y+diry[i]]!='*'&&c[x+dirx[i]][y+diry[i]]!='#'&&vis[x+dirx[i]][y+diry[i]]==0){
			vis[x+dirx[i]][y+diry[i]]=1;
			dfs(x+dirx[i],y+diry[i]);
			vis[x+dirx[i]][y+diry[i]]=0;//使用完记得还原
		}
	}
}
int main(){
	cin>>n>>m;
	int x,y;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cin>>c[i][j];
			if(c[i][j]=='S'){//标记王子位置
				x=i,y=j;
			}
			else if(c[i][j]=='E'){//标记公主位置
				dx=i,dy=j;
			}
		}
	}
	vis[x][y]=1;//这里王子刚开始的位置也一定要标记,不然可能会走回头路
	dfs(x,y);
	cout<<cnt<<endl;
	return 0;
}

 小B旅游

题目描述

小B在一个有N个城市M条道路的国家,每条道路连接的城市可以互相到达且每条道路小B都要花1步去走过它。现在他在1号城市,问他走P步最多能走多少个不同的城市? 
 

输入

输入格式:第1行,三个正整数N、M、P,意义如题:接下来M行,每行两个整数U、V,表示存在一条连接U、V的无向边。

输出

输出格式:1行,一个整数,表示从1号城市出发走P步的所有情况,共能经过多少个不同的城市。 

样例输入 Copy

4 4 2
1 2
1 3
2 3
3 4

样例输出 Copy

4

提示

数据规模:

 1<=N<=100000,1<=M<=5000000,1<=P<=10000

#include <bits/stdc++.h>
using namespace std;

int n,m,p;
set<int>se;//用来保存走过的城市数,去重 
struct node{
    int x,step;
};
vector<int> ve[100005];//表示两个城市的联通信 
int vis[100005];//表示是否访问过 
void bfs(){
    queue<node> q;
    node now,next;//当前点和下一个要访问的点 
    now.x=1,now.step=0;
    vis[1]=1;
    q.push(now);
    while(!q.empty()){
        now=q.front(),q.pop();
        for(int i=0;i<ve[now.x].size();++i){//bfs一层一层访问,
		//ve[now.x].size()表示now.x可以到达哪个城市,也就是和哪个城市是连通的 
            next.x=ve[now.x][i],next.step=now.step+1;
            if(vis[next.x]==0&&next.step<=p){
            se.insert(next.x);
                vis[next.x]=1;
                q.push(next);
            }
        }
    }
}
int main()
{
		ios::sync_with_stdio(false);
		cin.tie(0),cout.tie(0);
	    cin>>n>>m>>p;
        for(int i=1;i<=m;++i){
            int a,b;
            cin>>a>>b;
            ve[a].push_back(b);
            ve[b].push_back(a);
        }
        se.insert(1);//以1开始,因为为0是也可以到达自己,
		//但是就无法进入dfs的next.step=now.step+1; if判断条件 
        bfs();
        printf("%d\n",se.size());
    
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H-rosy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值