算法搜索练习
Posted karshey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法搜索练习相关的知识,希望对你有一定的参考价值。
DFS
注意搜索的顺序,是以树的形式。
Lake Counting
原题
输入
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
输出
3
题意:有几个水池。
思路:DFS,遇到连接的水池就继续搜,断开之后就记录。用dis[8][2]代表8个方向。范围是从1–n(列),1–m(行)。(通常x是横坐标,但是其实只要x在代码里的含义从一而终,都是可以过的,在这里x代表列(纵坐标))
注意:由于输入是没有空格的,直接以字符数组%s的形式输入会快:
for(int i=1;i<=n;i++)//n是列,从1开始
{
scanf("%s",mp[i]+1);//从1开始
}
总:
模板题
//DFS
#include<bits/stdc++.h>
using namespace std;
const int N=105,M=105;
int n,m;
char mp[N][M];
int dis[8][2]={-1,0,1,0,0,-1,0,1,-1,-1,-1,1,1,-1,1,1};
int v[N][M];
void dfs(int x,int y)
{
v[x][y]=1;
for(int i=0;i<8;i++)
{
int dx=x+dis[i][0];
int dy=y+dis[i][1];
//范围x:1~n,y:1~m
if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!v[dx][dy]&&mp[dx][dy]=='W')
{
dfs(dx,dy);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)//n是列
{
scanf("%s",mp[i]+1);//从1开始
}
int ans=0;
for(int i=1;i<=n;i++)//列循环在外
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='W'&&!v[i][j])
{
ans++;
dfs(i,j);
}
}
}
cout<<ans;
return 0;
}
Oil Deposits
题目链接
输入:
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
输出:
0
1
2
2
跟上面的水池问题其实一样。DFS即可。
如果发现输出不对可能是方向错了,如果发现输出多很多可能是条件少了…
//#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
using namespace std;
const int N=105;
//@有oil 可以斜着 diagonally
int dis[8][2]={1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};
char mp[N][N];
int ans=0;
int v[N][N];
int n,m;
void dfs(int x,int y)
{
v[x][y]=1;
for(int i=0;i<8;i++)
{
int xx=x+dis[i][0];
int yy=y+dis[i][1];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!v[xx][yy]&&mp[xx][yy]=='@')
{
dfs(xx,yy);
}
}
}
int main()
{
while(cin>>n>>m&&(n&&m))
{
for(int i=1;i<=n;i++)//列
{
for(int j=1;j<=m;j++)
{
cin>>mp[i][j];
}
}
ans=0;
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!v[i][j]&&mp[i][j]=='@')
{
ans++;
dfs(i,j);
//cout<<i<<" "<<j<<endl;
}
}
}
cout<<ans<<endl;
}
return 0;
}
棋盘问题
原题
输入:
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
输出:
2
1
因为每列最多只能有一个棋子,因为v可以用来记录此列是否有过棋子。
判断方法1:从右到左搜到头了,方案数+1;
//DFS
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int v[N];//记录此列是否有过
char mp[N][N];
int n,m;
int ans=0;
void dfs(int x,int y)
{
if(y==0) //从右向左搜到头了
{
ans++;
return;
}
if(x>n) return;//x超出范围了
for(int i=1;i<=n;i++)//每一列从左到右
{
if(mp[x][i]=='#'&&!v[i])//可以放棋子且没搜过
{
v[i]=1;
dfs(x+1,y-1);//下一行的左一列
v[i]=0;//搜完一轮后所有列清0;
}
}
dfs(x+1,y);
}
int main()
{
while(cin>>n>>m&&n!=-1)
{
memset(v,0,sizeof(v));
ans=0;
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
dfs(1,m);//从右上角开始搜
cout<<ans<<endl;
}
}
判断方法2:定义一个全局变量cheer来记录棋子数量,若cheer=要求的棋子数则方案数+1,记住cheer在搜索完之后要–(退回来后要取消标记,当作已经计算过这种情况,后重新计算别的情况 );
这里h代表行,v代表那一列有过棋子。一行行往下搜。
//DFS
#include<bits/stdc++.h>
using namespace std;
const int N=10;
char mp[N][N];
int n,k;
int cheer=0,ans=0;
int v[N];
void dfs(int h)
{
if(cheer==k)
{
ans++;
return;
}
if(h>n) return;
for(int i=1;i<=n;i++)
{
if(!v[i]&&mp[h][i]=='#')
{
v[i]=1;
cheer++;
dfs(h+1);
v[i]=0;//退回来后要取消标记,当作已经计算过这种情况,后重新计算别的情况
cheer--;
}
}
dfs(h+1);
}
int main()
{
while(cin>>n>>k&&(n!=-1))
{
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
ans=0;
cheer=0;
dfs(1);
cout<<ans<<endl;
}
}
BFS
Catch That Cow-HDU 2717
大意:多个样例,人抓牛,牛在K,人在N。人有两种走法,一步法的是向前一步或向后移,瞬移法是从n到2n,求抓到牛的最短时间。
此题是BFS,不是贪心
思路:从当前位置n开始,把所有可能到达的点搜索一遍。遇到k位置就输出时间。
注意:
- 范围,由于可以到达两倍的距离,所以范围是0~3*k。(因为可以超过k)
- 由于BFS是一圈一圈地搜索,每次记录的时间就已经是最短时间。(之后再记录就是下一圈,时间会边长,故第一次记录的是最短的)
模板题
//BFS
//#include<iostream>
//#include<queue>
//#include<string.h>
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
struct node
{
int pos,dis;
}a[N];
int vis[N];
int main()
{
int n,k;
while(cin>>n>>k)
{
memset(vis,0,sizeof(vis));
queue<node>q;
q.push({n,0});
vis[n]=1;
int ans=0;
while(!q.empty())
{
node temp=q.front();
if(temp.pos==k)
{
ans=temp.dis;
break;
}
q.pop();
if(vis[temp.pos+1]==0&&temp.pos+1<=3*k) {q.push({temp.pos+1,temp.dis+1});vis[temp.pos+1]=1;}
if(vis[temp.pos-1]==0&&temp.pos-1>=0) {q.push({temp.pos-1,temp.dis+1});vis[temp.pos-1]=1;}
if(vis[temp.pos*2]==0&&temp.pos*2<=3*k) {q.push({temp.pos*2,temp.dis+1});vis[temp.pos*2]=1;}
}
cout<<ans<<endl;
}
return 0;
}
Dungeon Master
原题
输入:
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0
输出:
Escaped in 11 minute(s).
Trapped!
三维的。模板题。BFS。
//BFS 最短时间
//L——lever;R---rows; C---colums
//每行C个字符 #不可走 .可走
#include<bits/stdc++.h>
using namespace std;
const int N=35;
char mp[N][N][N];
//int v[N][N][N];
int l,r,c;
struct node
{
int x,y,z;//坐标
int min;//时间
};
int dx[6]={-1,1,0,0,0,0};
int dy[6]={0,0,-1,1,0,0};
int dz[6]={0,0,0,0,-1,1};
int dis[N][N][N];
int sx,sy,sz,ex,ey,ez;
int bfs(int x,int y<以上是关于算法搜索练习的主要内容,如果未能解决你的问题,请参考以下文章