状压 bfs

http://119.23.43.230/problem.php?id=1234

题目描述

小z喜欢上了一个迷宫游戏,这个游戏是这样的,有一个N*M的迷宫(即N行M列的迷宫)保证0<N<=500,0<M<=500

左上角坐标(1,1)为入口,右下角坐标(N,M)为出口,这个迷宫和一般迷宫不同的地方是,

迷宫种可能会出现k个宝石(0<=k<=3),小z如果获得这些宝石那么在走到出口后就会有奖励,

同时游戏完成的出色程度也和小z走的步数有关,步数越小,奖励就越丰厚。

小z把迷宫的地图给你,想知道在尽可能获得更多的宝石的情况下,走出迷宫所需的最小步数是多少?如果无法走到出口,那么答案就是-1

输入

不会有多组输入数据

第一行两个整数N M,代表迷宫的行数和列数(N M中间以空格隔开)

之后N行每行M个数,每行的数之间用空格隔开,代表迷宫的地图

下面说一下地图元素的表示方法:

设A[i,j]为地图第i行第j列的元素

如果A[i,j]等于 -1 即代表地图第i行 第j列为障碍,不可到达,不可通过

如果A[i,j]不等于-1那么这个位置就是合法位置,玩家可以到达和通过

当然在i<0,j<0,i>N或者j>M这些情况下,坐标(i,j)已经超过了地图的边界,是不合法的

如果A[i,j]等于1、2或3,那么就代表(i,j)位置存在宝石,玩家走到该位置就自动获得这颗宝石

输出

输出只有一个整数,即所求答案

答案为在尽可能获得更多的宝石的情况下,走出迷宫所需的最小步数

如果无法走到出口,那么答案就是-1

样例输入

3 3
0 -1 1
0  0 0
0 -1 0

样例输出

6

思路 :这是一个状压bfs ,先dfs一遍是否能拿宝石,可以拿几个宝石。

宝石最多有3个 ,可以在001 表示只能1号宝石,010表示拿2号。100表示拿3号宝石

111表示全拿。用vis【】【】【】标记表示x,y,已经宝石拿的数量,进行bfs。

与hdu5094相似,比hdu5094简单

#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int M = 1e6 + 10;
int n,m;
int res=0;
int maps[510][510];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
bool vis[510][510][1<<4],vis1[510][510];
int jewel[510][510];
struct node
{
    int x,y,step,j,ans;
    node(){}
    node(int xx,int yy,int s,int jj,int as)
    {
        x=xx;y=yy;step=s;j=jj;ans=as;
    }
};
bool check(int x,int y)
{
    if(x<1||x>n||y<1||y>m)
        return 0;
    else
        return 1;
}
void bfs1()
{
    queue<P>q;
    P p;
    p.first=1;
    p.second=1;
    vis1[1][1]=1;
    if(maps[1][1]>0)
        res++;
    q.push(p);
    while(q.size())
    {
        P pp=q.front();
        q.pop();
      //  cout<<pp.first<<" "<<pp.second<<endl;
        for(int i=0;i<4;i++)
        {
            int xx=pp.first+dx[i],yy=pp.second+dy[i];
            if(!check(xx,yy))
                continue;
            if(!vis1[xx][yy])
            {
                if(maps[xx][yy]==-1)
                    continue;
                vis1[xx][yy]=1;
                p.first=xx;
                p.second=yy;
                if(maps[xx][yy]>0)
                    res++;
                q.push(p);
            }
        }
    }
}
int bfs()
{
    memset(vis,0,sizeof(vis));
    queue<node>q;
    int s;
    s=maps[1][1]>0?1:0;
    q.push(node(1,1,0,jewel[1][1],s));
    while(q.size())
    {
        node k=q.front();
        q.pop();
        int x=k.x,y=k.y,s=k.step,j=k.j,sum=k.ans;
       //cout<<x<<" "<<y<<" "<<sum<<" "<<j<<" "<<k.step<<" "<<res<<endl;
        if(x==n&&y==m&&sum==res)
                return s;
        for(int i=0;i<4;i++)
        {
            int xx=x+dx[i],yy=y+dy[i],jj=j;
            int ok = 0;
            if(maps[xx][yy]>0&& (jj&(jewel[xx][yy]))==0){
                 ok=1;
                 jj=jj|jewel[xx][yy];
            }
            if(!check(xx,yy))
                continue;
            if(maps[xx][yy]==-1||vis[xx][yy][jj])
                continue;
            vis[xx][yy][jj]=1;
            q.push(node(xx,yy,s+1,jj,sum+ok));
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        //FILE *out = fopen("D:\\maps.txt","w+");
        memset(maps,0,sizeof(maps));
        memset(jewel,0,sizeof(jewel));
        memset(vis1,0,sizeof(vis1));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&maps[i][j]);
                if(maps[i][j]>0)
                {
                    jewel[i][j]=(1<<(maps[i][j]-1));
                }
            }
        }/*
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(maps[i][j]!=-1)
                   fprintf(out,"%d ",maps[i][j]+1);
                else
               fprintf(out,"%d ",0);
            }
           fprintf(out,"\n");
       }
        fclose(out);*/
        res=0;
        bfs1();
        //cout<<res<<endl;
        int ans=bfs();
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liluoyu_1016/article/details/81316436
今日推荐