[POJ]week9

简单搜索题目:

深度优先搜索 (POJ 2488,POJ 3083,POJ 3009,POJ 1321,POJ 2251)
广度优先搜索(POJ 3278,POJ 1426,POJ 3126,POJ 3087.POJ 3414)
简单搜索技巧和剪枝(POJ 2531,POJ 1416,POJ 2676,POJ 1129)

2488.A Knight’s Journey

参考1

#include <cstdio>
#include <cstring>

using namespace std;

const int MAX_N = 27;
//字典序最小的行走方向
const int dx[8] = {
    
    -1, 1, -2, 2, -2, 2, -1, 1}; 
const int dy[8] = {
    
    -2, -2, -1, -1, 1, 1, 2, 2};
bool visited[MAX_N][MAX_N];
struct Step{
    
    
    char x, y;
} path[MAX_N];
bool success;           //是否成功遍历的标记
int cases, p, q;

void DFS(int x, int y, int num);

int main()
{
    
    
    scanf("%d", &cases);
    for (int c = 1; c <= cases; c++)
    {
    
    
        success = false;
        scanf("%d%d", &p, &q);
        memset(visited, false, sizeof(visited));
        visited[1][1] = true;    //起点
        DFS(1, 1, 1);              
        printf("Scenario #%d:\n", c);
        if (success)
        {
    
    
            for (int i = 1; i <= p * q; i++)
                printf("%c%c", path[i].y, path[i].x);
            printf("\n");
        }
        else
            printf("impossible\n");
        if (c != cases)
            printf("\n");      //注意该题的换行
    }
    return 0;
}

void DFS(int x, int y, int num)
{
    
    
    path[num].y = y + 'A' - 1;   //int 转为 char
    path[num].x = x + '0';
    if (num == p * q) 
    {
    
    
        success = true;
        return;
    }
    for (int i = 0; i < 8; i++)
    {
    
    
        int nx = x + dx[i];
        int ny = y + dy[i];
        if (0 < nx && nx <= p && 0 < ny && ny <= q
            && !visited[nx][ny] && !success)
        {
    
    
            visited[nx][ny] = true;
            DFS(nx, ny, num+1);
            visited[nx][ny] = false;    //撤销该步
        }
    }
}

3083.Children of the Candy Corn

参考1参考2

3009.Curling 2.0

参考1

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 25
using namespace std;
int h,w;//横纵坐标
int sx,sy,ex,ey;//起点 终点坐标
int ans;
int mp[Maxn][Maxn];
int dt[][2]= {
    
    {
    
    1,0},{
    
    -1,0},{
    
    0,1},{
    
    0,-1}};//4个方向
void dfs(int x,int y,int step) //在(x, y)位置上的步数step
{
    
    
    if(x==ex&&y==ey)//到达终点
    {
    
    
        if(step<ans)//若有更小值
            ans=step;
        return;
    }
    if(step==10||step>=ans)//若超过10步,或超过当前最短步数
        return;
    for(int i=0; i<4; i++)//四个方向搜索
    {
    
    
        int tx=dt[i][0]+x;
        int ty=dt[i][1]+y;
        while(tx>=0&&tx<h&&ty>=0&&ty<w&&mp[tx][ty]!=1)//若此方向能走,则走到尽头,直至出场或撞墙
        {
    
    
            if(tx==ex&&ty==ey)//若在过程中到达目标点
            {
    
    
                step++;
                if(step<ans)
                    ans=step;
                return;
            }
            tx+=dt[i][0];
            ty+=dt[i][1];
        }
        if((tx==x+dt[i][0]&&ty==y+dt[i][1])||tx<0||tx>=h||ty<0||ty>=w)//此方向不能走,或出场
            continue;
        mp[tx][ty]=0;//撞墙
        step++;
        dfs(tx-dt[i][0],ty-dt[i][1],step);
        step--;//回溯
        mp[tx][ty]=1;
    }
}
int main()
{
    
    
    while(cin>>w>>h,w+h)
    {
    
    
        ans=11;//初始化
        MEM(mp,0);
        for(int i=0; i<h; i++)
            for(int j=0; j<w; j++)
            {
    
    
                cin>>mp[i][j];
                if(mp[i][j]==2)
                {
    
    
                    sx=i;
                    sy=j;
                    mp[sx][sy]=0;
                }
                if(mp[i][j]==3)
                {
    
    
                    ex=i;
                    ey=j;
                }
            }
        dfs(sx,sy,0);//搜索
        if(ans==11)
            cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }
}

1321.棋盘问题

参考1

#include<iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
using namespace std;
int visit[20];
char mp[20][20];
int ans;//ans表示方案数
int k;//k表示棋子数目
int n;//n表示棋盘的大小
int DFS(int x,int y)
{
    
    
    if(y>=k)//判断是否棋子已经用完,如果用完,记录方案数加1,然后直接返回0
    {
    
    
        ans++;
        return 0;
    }
    for(int i=x;i<n;i++)
    {
    
    
        for(int j=0;j<n;j++)
        {
    
    
            if(!visit[j]&&mp[i][j]=='#')//标记数组仅仅标记某一列上是否有棋子,因为每次递归下一列,所以每一列不会有冲突,只需判断这一列上是否有其他棋子
            {
    
    
                visit[j]=true;//如果该位置该列没被标记且为棋盘,那么在这里放上棋子,并标记,
                DFS(i+1,y+1);//搜索下一列
                visit[j]=false;//还要注意修改标记后递归回来要及时复原
            }
        }
    }
    return 0;
}
int main()
{
    
    
    while(cin>>n>>k)
    {
    
    
        if(n==-1&&k==-1)
            break;
        memset(visit,false,sizeof(visit));
        memset(mp,false,sizeof(mp));
        for(int i=0;i<n;i++)
            cin>>mp[i];
        ans=0;
        DFS(0,0);
        cout<<ans<<endl;
    }
    return 0;
}

2251.Dungeon Master

参考1参考2

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define mod 1000000007
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int sl,sx,sy;
int el,ex,ey;
char mp[35][35][35];//记录地图
int vis[35][35][35];//标记是否走过
int base[6][3] = {
    
     {
    
    -1,0,0},{
    
    1,0,0},{
    
    0,-1,0},{
    
    0,1,0},{
    
    0,0,-1},{
    
    0,0,1} };//六个方向
int l,r,c;
struct node
{
    
    
    int f,x,y;//位置
    int step;//步数
    friend bool operator<(node a,node b)//步数小的现出来,即时间少
    {
    
    
        return a.step>b.step;//优先队列,步数小的先访问
    }
};
priority_queue<node>q;
/*************************bfs***************************/
void bfs()
{
    
    
    node p;
    p.f=sl;//初始化
    p.x=sx;
    p.y=sy;
    p.step=0;
    vis[sl][sx][sy]=1;
    q.push(p);
    while(!q.empty())
    {
    
    
        node s=q.top();
        q.pop();
        if(s.f==el&&s.x==ex&&s.y==ey)//满足条件
        {
    
    
            printf("Escaped in %d minute(s).\n",s.step);
            return;
        }
            for(int i=0; i<6; i++)//6种走法
            {
    
    
                int tl=s.f+base[i][0];
                int tx=s.x+base[i][1];
                int ty=s.y+base[i][2];
                if(mp[tl][tx][ty]!='#'&&tl>=0&&tl<l&&tx>=0&&tx<r&&ty>=0&&ty<c&&!vis[tl][tx][ty])//判断是否能走
                {
    
    
                    node e;
                    e.f=tl;
                    e.x=tx;
                    e.y=ty;
                    e.step=s.step+1;
                    vis[e.f][e.x][e.y]=1;
                    q.push(e);
                }
            }
    }
    cout<<"Trapped!"<<endl;
}
/**********************************主函数*********************************/
int main()
{
    
    
    while(cin >> l >> r >>c,l+r+c)
    {
    
    
        for(int i=0; i<l; i++)
        {
    
    
            for(int j=0; j<r; j++)
            {
    
    
                cin >> mp[i][j];
                for(int k=0; k<c; k++)
                {
    
    
                    if(mp[i][j][k]=='S')
                        {
    
    
                            sl=i;
                            sx=j;
                            sy=k;
                        }
                    if(mp[i][j][k]=='E')
                    {
    
    
                        el=i;
                        ex=j;
                        ey=k;
                    }
                }
            }
        }
        memset(vis,0,sizeof(vis));//每次都要初始化
        bfs();
    }
}

猜你喜欢

转载自blog.csdn.net/Jingle_dog/article/details/121872709