第五天 dfs

第五天 dfs

1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题解

#include<iostream>
#include<cstdio>
using namespace std;
char s[10][10];
bool f;
bool vis[10][10];
int dir[8][2] = {{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}};
bool in(int x,int y){
	return 0<=x && x<10 && 0<=y && y<9;
}
void dfs(int x,int y){
	if(f){
		return;
	}
	vis[x][y] = true;
	if(s[x][y] == 'T'){
		f = true;
		return; 
	}
	for(int i = 0;i<8;i++){
		int tx = x+dir[i][0];
		int ty = y+dir[i][1];
		if(in(tx,ty)&&!vis[tx][ty]&&s[tx][ty] != '#'){
			dfs(tx,ty);
		}
	}
}
int main(){
	int x,y;
	for(int i = 0;i<10;i++){
		scanf("%s",s[i]);
	}
	for(int i = 0;i<10;i++){
		for(int j = 0;j<9;j++){
			if(s[i][j] == 'S'){
				x = i;
				y = j;
			}
		}
	}
	dfs(x,y);
	if(f){
		cout <<"Yes"<<endl;
	}else{
		cout <<"No"<<endl;
	}
}

2
在这里插入图片描述
在这里插入图片描述

题解

#include<iostream>
#include<cstdio>
using namespace std;
char mp[105][105];
bool vis[105][105];
int n,m;
void dfs(int x,int y){
	if(x<0||x>=n||y<0||y>=m||vis[x][y]||mp[x][y] == '.'){
		return;
	}
	vis[x][y] = true;
	dfs(x-1,y);
	dfs(x,y-1);
	dfs(x+1,y);
	dfs(x,y+1);
}
int main(){
	int cnt = 0;
	scanf("%d%d",&n,&m);
	for(int i = 0;i<n;i++){
		scanf("%s",mp[i]);
	}
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			if(!vis[i][j] && mp[i][j] == '#'){
				dfs(i,j);
				cnt++;
			}
		}
	}
	cout <<cnt<<endl;
	return 0;
}

3
题目描述:

小信是一个玩迷宫的高手,天下还没有能难住他的迷宫。但是总有人喜欢刁难小信,不停的给小信出难题。这个出题的人很聪敏,他知道天下还没有能难住小信的迷宫。所以他便转换思维问小信,在不走重复路径的情况下,总共有多少不同可以到达终点的路径呢?小信稍加思索便给出了答案,你要不要也来挑战一下?

Input

第一行输入两个整数 n(1 ≤ n ≤ 11), m(1 ≤ m ≤ 11).表示迷宫的行和列。

然后有一个 n × m 的地图,地图由’.’、’#’、‘s’、‘e’这四个部分组成。’.‘表示可以通行的路,’#'表示迷宫的墙,'s’表示起始点,'e’表示终点。

Output

输出一个整数,表示从’s’到达’e’的所有方案数。

Sample Input 1

5 5
s####
.####
.####
.####
…e
Sample Output 1

1

Sample Input 2
3 3
s…
…#
…e

Sample Output 2
7
————————————————
题解

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,ans;
char mp[15][15];
bool vis[15][15];
void dfs(int x,int y){
	if(x<0||x>=n||y<0||y>=m||vis[x][y]||mp[x][y] == '#'){
		return;
	}
	if(mp[x][y] == 'e'){
		ans++;
	}
	vis[x][y] = true;
	dfs(x-1,y);
	dfs(x,y-1);
	dfs(x,y+1);
	dfs(x+1,y);
	vis[x][y] = false;
}
int main(){
	int x,y;
	scanf("%d%d",&n,&m);
	for(int i = 0;i<n;i++){
		scanf("%s",mp[i]);
	}
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			if(mp[i][j] == 's'){
				x = i;
				y = j;
			}
		}
	}
	dfs(x,y);
	cout <<ans<<endl;
	return 0;
} 

4
题目描述:

这一天蒜头君生日,他的朋友们一起来给蒜头君买一个大的蛋糕过生日。游戏做完后到了切蛋糕的时刻了,朋友们知道蒜头君喜欢吃蛋糕,便让蒜头君自己给自己切一块最大的。蒜头君看朋友们这么热情也就不客气了。

这块蛋糕是由 R \times CR×C 的网格构成,每个网格上面都放有不同的水果。蒜头君把这些水果分为两类,一类是自己喜欢吃的水果,用’#‘来表示;一类是自己不喜欢吃的水果,用’.'来表示。

蒜头君对切出的蛋糕有如下要求:

切出的蛋糕连成一块(可以不为矩形,但必须在网格上连通)
切出的蛋糕只包含自己喜欢吃的水果
请问,蒜头君最大可以吃到多大的蛋糕?

输入格式
第一行输入两个被空格隔开的整数 R(1 \le R \le 1000)R(1≤R≤1000) 和 C(1 \le C \le 1000)C(1≤C≤1000)。

然后会有一个 R \times CR×C 的网格,由’#‘和’.'组成。

输出格式
输出一个整数,表示蒜头君可以吃到的蛋糕最大是多少(即对应到网格中的格子数)。
输入样例:
5 6
.#…
…#…
…#…#
…###.
.#…
输出样例:
5
————————————————
题解

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,ans,cnt;
char mp[15][15];
bool vis[15][15];
void dfs(int x,int y){
	if(x<0||x>=n||y<0||y>=m||vis[x][y]||mp[x][y] == '.')
		return;
	cnt++;
	vis[x][y] = true;
	dfs(x-1,y);
	dfs(x,y-1);
	dfs(x,y+1);
	dfs(x+1,y);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i = 0;i<n;i++){
		scanf("%s",mp[i]);
	}
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			if(mp[i][j] == '#'&&!vis[i][j]){
				cnt = 0;
				dfs(i,j);
				if(ans < cnt){
					ans = cnt;
				}
			}
		}
	}

	cout <<ans<<endl;
	return 0;
} 

5
Description

中国象棋是起源于中国的一种棋戏,属于二人对抗性游戏的一种,在中国有着悠久的历史。由于用具简单,趣味性强,成为流行极为广泛的棋艺活动.

这一天小信迷上了中国象棋,在和一个大师的巅峰对决中处于下风.他知道自己再走三步大师就会赢下这一局。于是小信想背水一战。他想知道这个马三步可以到达的位置,是否有好的对策可以给大师致命一击。直接想出马三步能到达的所有位置,现在的小信已经大脑不能够用了。于是他找到他的好朋友你来帮忙解决这个问题。

马走动的方法是一直一斜,即先横着或直着走一格,然后再斜着走一个对角线,俗称“马走日”。马一次可走的选择点可以达到四周的八个点,故有“八面威风”之说。如果在要去的方向有别的棋子挡住,马就无法走过去,俗称“蹩马腿”(当然这里就没有蹩马腿了^ _ ^)。

Input

第一行输入两个整数 n (1 ≤ x ≤ 100), m(1≤ m ≤ 100) 代表棋盘行和列的大小。

第二行输入两个整数 x (1 ≤ x ≤ n), y (1 ≤ y ≤ m) 代表马开始所的位置。

Output

输出整个棋盘,’.‘代表棋盘上可以落子的点。’#'这个代表马三步能到达的点。

Sample Input 1
10 9
10 1
Sample Output 1



.#.#…
#.#.#…
####.#…
#####.#…
##.###…
#.###.#…
######…

——————————————

题解

#include<iostream>
#include<cstdio>
using namespace std;
int n,m;
char s[105][105];
int dir[8][2] = {{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}};
void dfs(int x,int y,int step){
	if(step > 3){
		return;
	}
	if(x<0||x>=n||y<0||y>=m){
		return;
	}
	s[x][y] = '#';
	for(int i = 0;i<8;i++){
		int tx = x+dir[i][0];
		int ty = y+dir[i][1];
		dfs(tx,ty,step+1);
	}
}
int main(){
	int x,y;
	scanf("%d%d%d%d",&n,&m,&x,&y);
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			s[i][j] = '.';
		}
	}
	dfs(x-1,y-1,0);
	for(int i = 0;i<n;i++){
		cout <<s[i]<<endl;
	}
	return 0;
}

6
在这里插入图片描述
在这里插入图片描述

题解

#include<iostream>
#include<cstdio>
using namespace std;
char mp[105][105];
bool vis[105][105][2];
bool f;
int n,m;
void dfs(int x,int y,int d){
	if(x<0||x>=n||y<0||y>=m||vis[x][y][d]||mp[x][y] == '#'){
		return;
	}
	vis[x][y][d] = true;
	dfs(x-(2-d),y,d);
	dfs(x+(2-d),y,d);
	dfs(x,y-(2-d),d);
	dfs(x,y+(2-d),d);
}
int main(){
	int x,y;
	scanf("%d%d",&n,&m);
	for(int i = 0;i<n;i++){
		scanf("%s",mp[i]);
	}
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			if(mp[i][j] == 'w'){
				x = i;
				y = j;
			}
		}
	}
	dfs(x,y,0);	
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			if(mp[i][j] == 'g'){
				x = i;
				y = j;
			}
		}
	}
	dfs(x,y,1);
	for(int i = 0;i<n;i++){
		for(int j = 0;j<m;j++){
			if(vis[i][j][0] && vis[i][j][1]){
				f = true;
			}
		}
	}
	if(f){
		cout <<"yes"<<endl;
	}else{
		cout <<"no"<<endl;
	}
	return 0;
} 

7
2020 年,蒜头君自己开了一家拥有 NN 个员工的大公司。每天,蒜头君都要分配 NN 项工作给他的员工,但是,由于能力的不同,每个人对处理相同工作所需要的时间有快有慢。众所周知,蒜头君是一个非常重视效率的人,他想知道该如何分配工作,才能使得完成所有工作的时间总和最小(每个员工只可以被分配到一个工作)。但是我们也都知道蒜头君不是一般的懒,所以蒜头君找到了你,请你拯救一下蒜头君吧!

输入格式
第一行输入一个整数 NN,代表有 NN 个员工,员工编号从 11 到 NN。(1 \le N \le 101≤N≤10)

接着输入一个 N*NN∗N 的二维矩阵 task[N][N]task[N][N],task[i][j]task[i][j] 指的是第 ii 项工作如果由 jj 号员工完成所需要的时间。(0 \le task[i][j] \le 10000≤task[i][j]≤1000)

输出格式
输出结果包括一个整数,代表所需要的最少时间(求和)。

样例输入
6
10 11 12 11 9 11
11 9 10 13 11 12
12 10 11 10 13 9
9 14 9 10 10 11
10 10 9 11 12 11
10 7 10 10 10 8
样例输出
54
————————————————

题解

#include<iostream>
#include<cstdio>
using namespace std;
int n;
int task[15][15];
bool used[15];
int ans = 10005;
void dfs(int x,int t){
	if(x == n){
		if(t < ans){
			ans = t;
		}
		return;
	}
	for(int i = 0;i<n;i++){
		if(!used[i]){
			used[i] = true;
			dfs(x+1,t+task[x][i]);
			used[i] = false;
		}
	}
}
int main(){
	scanf("%d",&n);
	for(int i = 0;i<n;i++){
		for(int j = 0;j<n;j++){
			scanf("%d",&task[i][j]);
		}
	}
	dfs(0,0);
	cout <<ans<<endl;
	return 0;
}

8
蒜头君手上有一些小木棍,它们长短不一,蒜头君想用这些木棍拼出一个等边三角形,并且每根木棍都要用到。 例如,蒜头君手上有长度为 11,22,33,33 的4根木棍,他可以让长度为11,22 的木棍组成一条边,另外 22 跟分别组成 22条边,拼成一个边长为 33 的等边三角形。蒜头君希望你提前告诉他能不能拼出来,免得白费功夫。

输入格式
首先输入一个整数 n(3 \le n \le 20)n(3≤n≤20),表示木棍数量,接下来输入 nn 根木棍的长度 p_i(1 \le p_i \le 10000)p
​i
​​ (1≤p
​i
​​ ≤10000)。

输出格式
如果蒜头君能拼出等边三角形,输出"yes",否则输出"no"。

样例输入1
5
1 2 3 4 5
样例输出1
yes
样例输入2
4
1 1 1 1
样例输出2
no
————————————————

题解

#include<iostream>
#include<cstdio>
using namespace std;
int n;
int p[15];
int sum;
bool f;
bool vis[15];
void dfs(int cnt,int s,int st){ //选了几根木棍,木棍总长度,从第几根木棍开始选 
	if(f){
		return;
	}
	if(cnt == 3){
		f = true;
		return;
	}
	if(s == sum/3){
		dfs(cnt+1,0,0);
		return;
	}
	for(int i = 0;i<n;i++){
		if(!vis[i]){
			vis[i] = true;
			dfs(cnt,s+p[i],i+1);
			vis[i] = false;
		}
	}
}
int main(){
	scanf("%d",&n);
	for(int i = 0;i<n;i++){
		scanf("%d",&p[i]);
		sum += p[i];
	}
	if(sum % 3 != 0){
		cout <<"no"<<endl;
	}else{
		dfs(0,0,0);
		if(f){
			cout <<"yes"<<endl;
		}else{
			cout <<"no"<<endl; 
		} 
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值