hdu 2416 (搜索)

题意:给出一个图,$是宝藏的位置,图的边界上有一些入口,#代表没有没有炸药,A—Z代表炸药的数量,只能从一个入口进入,图中有一些数字代表石头,如果消耗一个炸药炸掉石头不花时间,不炸的话会消耗相应的时间,问最少到达宝藏地点的时间是多少。

思路:刚开始想着直接广搜,写了一会就觉得不行,如果到达一点有几条路径的时间相同,我们应该去携带炸药最多的,那样能保证后面的时间最少。所以把图增加成三维地图,记录到达每点携带的炸药数量的最短时间。




#include<iostream>
#include<queue>
using namespace std;
const int N=110;
const int inf=0x3fffffff;
int dir[4][2]={0,1,0,-1,1,0,-1,0},n,m,t[N][N][27];
bool vis[N][N][27];
char map[N][N];
struct node
{
    int x,y,k;
}cur,next;
bool judge(int x,int y)
{
    if(x<0||x>=n||y<0||y>=m||map[x][y]=='*')return false;
    return true;
}
void bfs()
{
    int i,j,x,y,ii,k,sx,sy,ans=inf;
    queue<node>Q;
    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)
        {
            for(ii=0;ii<27;ii++)
            t[i][j][ii]=inf,vis[i][j][ii]=false;
            if(map[i][j]=='$') sx=i,sy=j;              
            else if(map[i][j]=='#'||map[i][j]>='A'&&map[i][j]<='Z')
            {
                cur.x=i;cur.y=j;
                if(map[i][j]=='#')cur.k=0;
                else cur.k=map[i][j]-'A'+1;
                Q.push(cur);
                map[i][j]='*';t[i][j][cur.k]=0;vis[i][j][cur.k]=true;
            }
        }
    }
    while(!Q.empty())
    {
        cur=Q.front();Q.pop();   
        vis[cur.x][cur.y][cur.k]=false;
        for(i=0;i<4;i++)
        {
            next.x=x=cur.x+dir[i][0];
            next.y=y=cur.y+dir[i][1];
            next.k=k=cur.k;
            if(!judge(x,y))continue;
            if((map[x][y]=='.'||map[x][y]=='$')&&t[x][y][k]>t[cur.x][cur.y][k])//直接走过
            {
                t[x][y][k]=t[cur.x][cur.y][k];
                if(!vis[x][y][k]){Q.push(next);vis[x][y][k]=true;}
            }
            else if(map[x][y]>='1'&&map[x][y]<='9')
            {
                int temp=map[x][y]-'0';
                if(t[x][y][k]>t[cur.x][cur.y][k]+temp)//不炸
                {
                    t[x][y][k]=t[cur.x][cur.y][k]+temp;
                    if(!vis[x][y][k]){Q.push(next);vis[x][y][k]=true;}
                }
                if(k>0&&t[x][y][k-1]>t[cur.x][cur.y][k])//炸
                {
                    next.k--;
                    t[x][y][k-1]=t[cur.x][cur.y][k];
                    if(!vis[x][y][k-1]){Q.push(next);vis[x][y][k-1]=true;}
                }
            }
        }
    }
    for(i=0;i<27;i++)
        if(ans>t[sx][sy][i]){ans=t[sx][sy][i];}
    if(ans<inf)printf("%d\n",ans);
    else printf("IMPOSSIBLE\n");
}
int main()
{
    n=0;
    while(gets(map[n]),map[n][0]!='-')
    {
        if(map[n][0]=='\0')
        {
            m=strlen(map[0]);
            bfs();n=-1;           
        }
        n++;
    }
    return 0;
}


你可能感兴趣的:(编程,算法,搜索,百度,ACM)