搜索入门

A - Lake Counting POJ - 2386

题意:W是水洼,连起来的W算同一个水洼(是九宫格内的连起来)

解题思路:dfs搜索,搜索不到了就继续,每一个dfs都可以搜到一个水坑,简而言之,总的dfs的次数就是水坑的个数(dfs重新调用的dfs不算)
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
#define PI 3.14159265358979323846264338327950

int N,M;
const int MAX_N=103;
char field[MAX_N][MAX_N];

void dfs(int x,int y)
{
    field[x][y]='.';
    for(int dx=-1;dx<=1;dx++)
    {
        for(int dy=-1;dy<=1;dy++)
        {
            int nx=x+dx,ny=y+dy;
            if(0<=nx && nx<N && 0<=ny && ny<M && field[nx][ny]=='W')
                dfs(nx,ny);
        }
    }
    return ;
}

void solve()
{
    int res =0;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<M;j++)
        {
            if(field[i][j]=='W')
            {
                dfs(i,j);
                res++;
            }
        }
    }
    printf("%d
",res);
}

int main()
{
    cin>>N>>M;
    for(int i=0;i<N;i++)
        for(int j=0;j<M;j++)
            cin>>field[i][j];
    solve();
    
}
View Code

B - N皇后问题 HDU - 2553 

 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。 
你的任务是,对于给定的N,求出有多少种合法的放置方法。 

Input共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。Output共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。Sample Input

1
8
5
0

Sample Output

1
92
10


解题思路:可以说是入门的dfs了,直接用数组的i来储存行就不用考虑行的重复了, 只需要进行对列和对角线的判断就好了,先打个表,不然可能会超时哦

#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
#define PI 3.14159265358979323846264338327950

int map[12],a[12],n,sum;

int check(int x)
{
    for(int i=0;i<x;i++)
    {
        if(map[i]==map[x]||abs(map[i]-map[x])==abs(i-x))
            return 0;
    }
            return 1;
}
void dfs(int x)
{
    if(x==n)
        sum++;
    else
    {
        for(int j=1;j<=n;j++)
        {
            map[x]=j;
            if(check(x))
                dfs(x+1);
        }
    }
}

int main()
{
    for(int i=1;i<11;i++)
    {
        sum=0;
        n=i;
        dfs(0);
        a[i]=sum;
    }
    int n;
    while(scanf("%d",&n) && n)
    {
        printf("%d
",a[n]);
    }
}
View Code

C - Catch That Cow POJ - 3278 

题目大意:人追牛,人可以加减一步或者两倍

解题思路:就是bfs搜索,注意数组的大小要开两倍
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
#define PI 3.14159265358979323846264338327950

struct point
{
    int x,y,step;
}st;

queue<point>q;
int vis[200002];
int n,m,flat;

int bfs()
{
    while(!q.empty())
    {
        q.pop();
    }
    
    memset(vis,0,sizeof(vis));
    vis[st.x]=1;
    q.push(st);
    while(!q.empty())
    {
        point now=q.front();
        if(now.x==m)
            return now.step;
        q.pop();
        for(int j=0;j<3;j++)
        {
            point next = now;
            if(j == 0)
                next.x=next.x+1;
            else if(j==1)
                next.x=next.x-1;
            else
                next.x=next.x*2;
            ++next.step;
            if(next.x==m)
                return next.step;
            if(next.x>=0 && next.x<=200000 && !vis[next.x])
            {
                vis[next.x]=1;
                q.push(next);
            }
        }
    }
    return 0;
}
int main()
{
    while (~scanf("%d %d", &n, &m))
    {
        st.x = n;
        st.step=0;
        printf("%d
", bfs());
    }
  return 0;
        
}
View Code

D - Dungeon Master POJ - 2251 

题意:给你一个多维的迷宫,问能不能可以从起点走到终点,可以上下穿梭层数,也可以东南西北走,都是一秒一个单位,可以到终点就输出步数,不可以就输出那句话

解题思路:其实和普通的二维迷宫差不多,就是多了一个层数,也就是多了两个方向(上下层数)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define ll long long
int const maxn = 35;
const int mod = 1e9 + 7;
int gcd(int a, int b) {
    if (b == 0) return a;  return gcd(b, a % b);
}

char map[maxn][maxn][maxn];
int vis[maxn][maxn][maxn];
int k,n,m,sx,sy,sz,ex,ey,ez;
int dir[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};

struct node
{
    int x,y,z,step;
};
int check (int x,int y,int z)
{
    if(x<0 || y<0 || z<0 || x>=k || y>=n || z>=m)
        return 1;
    else if(map[x][y][z]=='#')
        return 1;
    else if(vis[x][y][z])
        return 1;
    return 0;
}

int bfs()
{
    node a,next;
    queue<node>que;
    a.x=sx;  a.y=sy;  a.z=sz;
    a.step=0;
    vis[sx][sy][sz]=1;
    que.push(a);
    while(!que.empty())
    {
        a=que.front();
        que.pop();
        if(a.x == ex && a.y == ey && a.z == ez)
            return a.step;
        for(int i=0;i<6;i++)
        {
            next=a;
            next.x=a.x+dir[i][0];
            next.y=a.y+dir[i][1];
            next.z=a.z+dir[i][2];
            if(check(next.x,next.y,next.z))
                continue;
            vis[next.x][next.y][next.z]=1;
            next.step=a.step+1;
            que.push(next);

        }
    }
    return 0;

}


int main()
{
    while(~scanf("%d %d %d",&k,&n,&m))
    {
        if(k==0 && n==0 && m==0)
            break;
        for(int i=0;i<k;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%s",map[i][j]);
                for(int r=0;r<m;r++)
                {
                    if(map[i][j][r]=='S')
                    {
                        sx=i;sy=j;sz=r;
                    }
                    else if(map[i][j][r]=='E')
                    {
                        ex=i;ey=j;ez=r;
                    }
                }
            }
        }
        memset(vis,0,sizeof(vis));
        int ans;
        ans=bfs();
        if(ans)
            printf("Escaped in %d minute(s).
",ans);
        else
            printf("Trapped!
");
    }
    return 0;
}
View Code

E - Prime Path HDU - 1973

题意:给你两个四位数,都是素数,每次改变可以改变其中的任何一个数字,但要求改变后的四位数(没有前导零)依然是素数,问最少改变几次可以使得第一个数改为第二个数

思路:可以先用埃氏筛法把1000-9999的所有的素数都选出来,之后就四个位数,每个位数最多改变八次,就搜索一下,我开了isprime和step两个数组,当然也可以开一个结构体,但只改变一个数字需要花点功夫,我是枚举了个位,十位,百位,千位。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define ll long long
int const maxn = 9999;
const int mod = 1e9 + 7;
int gcd(int a, int b) {
    if (b == 0) return a;  return gcd(b, a % b);
}

bool isprime[maxn];
int step[maxn];
bool vis[maxn];
int num1,num2;
void getprime(int n)
{
    for(int i=0;i<=n;i++)
        isprime[i]=true;
    isprime[0]=isprime[1]=false;
    for(int i=2;i<=n;i++)
    {
        for(int j=2*i;j<=n;j=j+i)
            isprime[j]=false;
    }
}

int bfs(int st )
{
 
    vis[st]=true;
    step[st]=0;
    queue<int>que;
    que.push(st);
    while(que.size())
    {
        int p=que.front();
        que.pop();
        if(p == num2)
        {
            return step[num2];
            break;
        }
        int ge=p % 10;
        int shi=(p/10)%10;
        int bai=(p/100)%10;
        int qian=p/1000;
        for(int i=0;i<=9;i++)
        {
            int next;
            if(i!=ge)
            {
                next=p-ge+i;
                if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false)
                {
                    step[next]=step[p]+1;
                    que.push(next);
                    vis[next]=true;
                    //   cout<<"ge";
                }
            }
            if(i!=shi)
            {
                next=p-shi*10+i*10;
                if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false)
                {
                    step[next]=step[p]+1;
                    que.push(next);
                    vis[next]=true;
                //    cout<<"shi";
                }
            }
            if(i!=bai)
            {
                next=p-bai*100+i*100;
                if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false)
                {
                    step[next]=step[p]+1;
                    que.push(next);
                    vis[next]=true;
                //    cout<<"bai";
                }
            }
            if(i!=qian)
            {
                next=p-qian*1000+i*1000;
                if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false)
                {
                    step[next]=step[p]+1;
                    que.push(next);
                    vis[next]=true;
               //     cout<<"qian";
                }
            }
        }
            
    }
    return -1;
}
int main()
{
    int t;
    scanf("%d",&t);
    getprime(9999);
    while(t--)
    {
        memset(vis,false,sizeof(vis));
        memset(step,0,sizeof(step));
        scanf("%d %d",&num1,&num2);
        
//        for(int i=2;i<=9999;i++)
//            if(isprime[i])
//                cout<<i<<" ";
        int ans=bfs(num1);
        if(ans>=0)
          printf("%d
",ans);
        else
            printf("Impossible
");
    }
}
View Code
原文地址:https://www.cnblogs.com/smallhester/p/10296264.html