浏览器标题切换
浏览器标题切换end

POJ3009 - Curling 2.0 - DFS+方向直线移动

题意

给出一个 m x n 的图,图中有 1234数字,分别表示: 0 空地、 1 障碍物、 2 起点、 3 终点。

让我们输出:从起点( S )到终点( G )的最小步数,无法达到输出 1

要求:

  1. 仅限 xy 方向(即禁止对角线移动)。

  2. 石头一旦开始移动,只能沿着这一个方向一直移动,除非下列任一事件发生:

    • 石头击中黑色方块。

    • 石块飞出游戏板之外(即超出图的边界)。

    • 石头停在他击中的砖块之前被击中的砖块消失(也就是说,如果石头走到障碍物的四周,那么可以换方向走,该障碍物消失变成空地 0)。

  3. 步数不能超过 10 步。

思路

正确的思路是:先找到起点 S ,然后将该点由 2 变为 0 ,表示是空地,可以走(本来也可以走)。

然后开始从 S 开始搜,

关键点主要是:不一次一格走,而是一次一条线走,该如何写?其实通过一个while和一个方向累加就行了,

while(tx>=1&&tx<=n&&ty>=1&&ty<=m&&a[tx][ty]==0)
            tx+=to[i][0],ty+=to[i][1];

之后如果碰到终点了,那么直接 更新+return 就行了。

排除所有碰到终点呀、越界呀这些情况,最后开始继续往下搜,首先把障碍物消除,变为空地 0 ,搜索,把障碍物还原变为 1
其实我的思路是BFS,因为求最小步数嘛,但是我不会写……

这是我写的BFS部分代码:

#include<iostream>
#include<cmath>
#include<string.h>
#include<queue>
using namespace std;
typedef long long ll;
#define inf 03f3f3f3f

char s[22][22];
int n,m,s,t,ss,tt;
bool book[22][22];
int to[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
typedef pair<int,int>P;

int bfs()
{
    memset(dis,inf,sizeof(dis));
    dis[s][t]=0;
    queue<P>Q;
    Q.push(P(s,t));
    while(!Q.empty())
    {
        P x=Q.front();
        Q.pop();
        if(x.first==ss&&x.second==tt)
            break;
        for(int i=0;i<4;i++)
        {
            int tx=x.first+to[i][0];
            int ty=x.second +to[i][1];
            if(tx>=0&&tx<n&&ty>=0&&ty<m&&s[tx][ty]!='#'&&d[tx][ty]==inf)
            {
                Q.push(P(tx,ty));
                dis[tx][ty]=dis[x.first][x.second]+1;
            }
        }
    }
    return dis[ss][tt];
}

int main()
{
	while(cin>>m>>n)
	{
	    if(m==0&&n==0) 
	        break;
        for(int i=0;i<n;i++)
        {
            scanf("%s",s[i]);
             for(int j=0;j<m;j++)
            {
                 if(s[i][j]=='S')
                   s=i,t=j;        
                 else if(s[i][j]=='G')
                    ss=i,tt=j;
          }
        }
        int w=bfs();
        if(w==inf)
            cout<<-1<<endl;
        else
            cout<<w<<endl;
	}
   
	return 0;
}

AC代码

#include<iostream>
#include<cmath>
#include<string.h>
#include<queue>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f

int a[22][22],n,m,s,t,ss,tt,ans;
bool book[22][22];
int to[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
typedef pair<int,int>P;

void dfs(int x,int y,int step)
{
    if(step>=ans||step>=10) return ;
    for(int i=0;i<4;i++)
    {
        int tx=x+to[i][0];
        int ty=y+to[i][1];
        if(a[tx][ty]==1) // 遇到障碍物
            continue ;
        while(tx>=1&&tx<=n&&ty>=1&&ty<=m&&a[tx][ty]==0)
            tx+=to[i][0],ty+=to[i][1];
        if(tx>=1&&tx<=n&&ty>=1&&ty<=m)
        {
            if(a[tx][ty]==3) // 0空地、1障碍物、2起点、3终点
            {
                ans=step+1;
                return ;
            }
            a[tx][ty]=0; //消去障碍物
            dfs(tx-to[i][0],ty-to[i][1],step+1);
            a[tx][ty]=1;
        }
    }
}

int main()
{
	while(cin>>m>>n)
	{
	    if(m==0&&n==0) 
	        break;
	    //0空地、1障碍物、2起点、3终点
	    ans=inf;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>a[i][j];
                if(a[i][j]==2)
                    a[i][j]=0,s=i,t=j;
            }
        }
        dfs(s,t,0);
        if(ans!=inf)
            cout<<ans<<endl;
        else
            cout<<-1<<endl;
	}
	return 0;
}   
posted @   抓水母的派大星  阅读(119)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示