【暑假复习】【搜索】POJ3009:Curling 2.0

题意

给出一个图,有石头和空地,有一个球,可以向上下左右任意一个没有相邻石头的方向持续移动,直到撞到石头为止(球停留在石头的前一格),并且会使撞到的石头消失,求让球到达目的地最少的步数(不一定非要在终点停下,经过即可视为抵达),且步数必定小于等于10,否则算无解。如果没有合法方案,也属于无解,无解输出-1


题解

因为步数必然小于10,所以枚举每一步走上下左右的某一个方向即可,判断是否合法,然后转移。
时间复杂度为4的n次方,n<=10。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 30
using namespace std;
int ma[MAXN][MAXN],n,m,w[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
queue<pair<int,int> >q;
pair<int,int> st,ed;
int get_lx(int x,int y,int f){
    if(f==0)
        return x;
    int x1=x+f;
    while(ma[x1][y]!=1&&x1>=0&&x1<=n+1){
        if(x1==ed.first&&y==ed.second){
            x1+=f;
            break;
        }
        x1+=f;
    }
    return x1-f;
}
int get_ly(int x,int y,int f){
    if(f==0)
        return y;
    int y1=y+f;
    while(ma[x][y1]!=1&&y1>=0&&y1<=m+1){
        if(x==ed.first&&y1==ed.second){
            y1+=f;
            break;
        }
        y1+=f;
    }
    return y1-f;
}
int check1(int x,int y){
    if(x*y==0||x>n||y>m)
        return 0;
    if(ma[x][y]==1)
        return 0;
    return 1;
}
int dfs(int x,int y,int cnt){
    //PF("(%d %d %d)\n",x,y,cnt);
    if(cnt>10)
        return 11;
    if(x==ed.first&&y==ed.second)
        return cnt;
    int res=11;
    for(int i=0;i<4;i++){
        if(check1(x+w[i][0],y+w[i][1])==0)
            continue;
        int x1=get_lx(x,y,w[i][0]);
        int y1=get_ly(x,y,w[i][1]);
        if(check1(x1,y1)){
            int sig=0;
            if(ma[x1+w[i][0]][y1+w[i][1]]==1)
                sig=1;
            ma[x1+w[i][0]][y1+w[i][1]]=0;
            res=min(res,dfs(x1,y1,cnt+1));
            if(sig==1)
                ma[x1+w[i][0]][y1+w[i][1]]=1;
        }
    }
    return res;
}
int main(){
    SF("%d%d",&m,&n);
    int x;
    while(n*m!=0){
        memset(ma,0,sizeof ma);
        while(!q.empty())
            q.pop();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                SF("%d",&x);
                if(x==2)
                    st=make_pair(i,j);
                else if(x==3)
                    ed=make_pair(i,j);
                else if(x==1)
                    ma[i][j]=1;
            }
        int ans=dfs(st.first,st.second,0);
        if(ans==11)
            PF("-1\n");
        else
            PF("%d\n",ans);
        SF("%d%d",&m,&n);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值