hdu 1044 Collect More Jewels(bfs+dfs)

题目链接:哆啦A梦传送门

 

参考链接:https://www.cnblogs.com/kuangbin/archive/2012/08/14/2637512.html

题意:给一个迷宫图,让你在不超过时间L的情况下从起点走到终点,图中有些点是有宝藏的,经过这个点会得到相应的宝藏价值,'@'表示起点,'<'表示终点,'*'表示墙,'.'表示空地,‘A'~’J'表示宝藏;

题解:我们先设起点为0,终点为M+1,宝藏点为相应的字符顺序。

那么我们先bfs找出任意两点的最短距离,也就是走到此点的时间。

最后我们dfs找出源点到终点的最大值。

 

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

int dis[55][55];///存储两点之间的最短距离
int step[55][55];///bfs时记录步数
int used[55][55];///bfs时标记此点是否访问
char maps[55][55];
int val[15];///存储宝藏的值
int sum;///存储珠宝总价值
int vis[55];///dfs标记此点是否访问
int ans;///结果最大值

int W,H,L,M;

int dx[4][2]={0,1,0,-1,1,0,-1,0};
queue<int> que;

///bfs,找s到其它点(1~M)的最短距离
void bfs(int x1,int y1,int s)
{
    while(!que.empty()) que.pop();

    memset(used,0,sizeof(used));
    memset(step,0,sizeof(step));
    used[x1][y1]=1;
    step[x1][y1]=0;

    que.push(x1*W+y1);///把此点push进去

    while(!que.empty())
    {
        int t=que.front();

        que.pop();
        int x=t/W;
        int y=t%W;

        for(int i=0;i<4;i++)
        {
            int xx=x+dx[i][0];
            int yy=y+dx[i][1];
            if(xx<0||xx>=H||yy<0||yy>=W) continue;
            if(used[xx][yy]||maps[xx][yy]=='*') continue;

            used[xx][yy]=1;
            step[xx][yy]=step[x][y]+1;

            if(maps[xx][yy]=='@'){
                dis[s][0]=step[xx][yy];
            }
            else if(maps[xx][yy]=='<')
                dis[s][M+1]=step[xx][yy];
            else if(maps[xx][yy]>='A'&&maps[xx][yy]<='J')
                dis[s][maps[xx][yy]-'A'+1]=step[xx][yy];

            que.push(xx*W+yy);
        }
    }
    return;
}

void dfs(int s,int value,int time)
{
    ///剪枝
    if(time>L) return; ///时间超过L
    if(ans==sum) return;

    if(s>M){ ///到达终点
        ans=max(ans,value);
        return;
    }

    for(int i=0;i<=M+1;i++)
    {
        if(vis[i]||dis[s][i]==0) continue;

        vis[i]=1;
        dfs(i,value+val[i],time+dis[s][i]);
        vis[i]=0;
    }
    return;
}
int main()
{
    int ncase;

    scanf("%d",&ncase);
    int T=0;

    while(ncase--)
    {
        scanf("%d%d%d%d",&W,&H,&L,&M);

        sum=0;
        for(int i=1;i<=M;i++)
            scanf("%d",&val[i]),sum+=val[i];

        memset(dis,0,sizeof(dis));
        val[0]=0;val[M+1]=0;///起点和终点都为价值都为0

        for(int i=0;i<H;i++)
            scanf("%s",&maps[i]);

        for(int i=0;i<H;i++)
            for(int j=0;j<W;j++)
        {

            if(maps[i][j]=='@'){///定义起点为第0个点
                bfs(i,j,0);
            }
            else if(maps[i][j]=='<') ///终点为第M+1个点
                bfs(i,j,M+1);
            else if(maps[i][j]>='A'&&maps[i][j]<='J')
                bfs(i,j,maps[i][j]-'A'+1);
        }

        memset(vis,0,sizeof(vis)); ///初始化
        vis[0]=1;
        ans=-1;
        dfs(0,0,0);

        printf("Case %d:\n",++T);
        if(ans>=0) printf("The best score is %d.\n",ans);
        else printf("Impossible\n");

        if(ncase) puts("");


    }


    return 0;
}

 

我虽说不爱这类dfs,bfs,但我还是要做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值