第五天 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;
}
}
}