hdu1044Collect More Jewels(bfs+dfs)

->题目请戳这里<-

题目大意:迷宫问题。在一个h * w的地图上,@代表起始位置,"."代表空地,"<"代表出口,"A"-"J"代表不同的宝物,不同的宝物有不同的价值,给定一个时间l,要求在l的时间内走出这个迷宫,并要带走最大价值的宝物,求最优解,无法逃出迷宫输出“Impossible”。

题目分析:既然明显是迷宫问题,肯定要搜索。但这题不是简单的要求逃出迷宫就行了,还要求尽可能的带走价值最大的宝物,而宝物的相对位置未知,所以盲目的搜索会产生大量的重复搜索量,所以先bfs求出各宝物以及起点、终点的相对位置,宝物不超过10个,然后再进行dfs遍历所有可能的情况,取最优解即可,这样可以省略大量的无用搜索步骤,节省时间。详情请见代码:

#include <iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;

const int N = 51;
#define INF 0x3f3f3f3f
char graph[N][N];
int h,w,l,m,sum;
int si,sj,ei,ej;
int ans,ok;
int value[15];
int dis[N][N];
//起点、终点以及各珠宝之间的距离,0代表起点,1-m代表m种珠宝,m + 1代表终点
int dir[][2] = {{0,1},{0,-1},{1,0},{-1,0}};
bool flag[N][N];
bool vis[15];
struct node
{
    int i,j,step;
}s,now;
queue<struct node>lcm;

int min(int a,int b)
{
    return a > b?b:a;
}

void dfs(int cur,int time,int cal)
{
    if(time < 0)
        return;
    if(ans == sum)
        return;
    if(cur == m + 1)
    {
        if(ans < cal)
            ans = cal;
        return;
    }
    int i;
    for(i = 1;i <= m + 1;i ++)
    {
        if(!vis[i])
        {
            vis[i] = 1;
            dfs(i,time - dis[cur][i],cal + value[i - 1]);
            vis[i] = 0;
        }
    }
}

void bfs()
{
    while(!lcm.empty())
        lcm.pop();
    //printf("%c\n",graph[s.i][s.j]);
    int i;
    int start;
    if(graph[s.i][s.j] == '@')
        start = 0;
    else
    {
        start = graph[s.i][s.j] - 64;
    }
    dis[start][start] = 0;
    s.step = 0;
    lcm.push(s);
    memset(flag,0,sizeof(flag));
    flag[s.i][s.j] = 1;
    while(!lcm.empty())
    {
        now = lcm.front();
        lcm.pop();
        for(i = 0;i < 4;i ++)
        {
            s = now;
            s.i += dir[i][0];
            s.j += dir[i][1];
            if(s.i >= h || s.i < 0 || s.j >= w || s.j < 0)
                continue;
            if(graph[s.i][s.j] == '*' || flag[s.i][s.j])
                continue;
            s.step = now.step + 1;
            if(graph[s.i][s.j] == '<')
            {
                dis[start][m + 1] = min(dis[start][m + 1],s.step);
                dis[m + 1][start] = dis[start][m + 1];
            }
            else
            {
                if(graph[s.i][s.j] >= 'A' && graph[s.i][s.j] <= 'J')
                {
                    dis[start][graph[s.i][s.j] - 64] = min(dis[start][graph[s.i][s.j] - 64],s.step);
                    dis[graph[s.i][s.j] - 64][start] = dis[start][graph[s.i][s.j] - 64];
                }
            }
            lcm.push(s);
            flag[s.i][s.j] = 1;
        }
    }
}


int main()
{
    int i,j,t;
    int cas = 0;

    scanf("%d",&t);
    while(t --)
    {
        sum = 0;
        scanf("%d%d%d%d",&w,&h,&l,&m);
        for(i = 0;i < m;i ++)
        {
            scanf("%d",&value[i]);
            sum += value[i];
        }
        value[m] = 0;
        getchar();
        for(i = 0;i < h;i ++)
            scanf("%s",graph[i]);
        memset(dis,0x3f,sizeof(dis));
        for(i = 0;i < h;i ++)
        {
            for(j = 0;j < w;j ++)
            {
                if(graph[i][j] == '*')
                    continue;
                if(graph[i][j] == '@')
                {
                    si = i;
                    sj = j;
                    s.i = i;
                    s.j = j;
                    bfs();
                    //printf("@isok\n");
                }
                else
                {
                    if(graph[i][j] >= 'A' && graph[i][j] <= 'Z')
                    {
                        s.i = i;
                        s.j = j;
                        bfs();
                        //printf("%cisok\n",graph[i][j]);
                    }
                    else
                    {
                        if(graph[i][j] == '<')
                        {
                            ei = i;
                            ej = j;
                        }
                        else
                            continue;
                    }
                }
            }
        }
        printf("Case %d:\n",++cas);
        if(dis[0][m + 1] > l)
        {
            printf("Impossible\n");
            if(t)
                printf("\n");
            continue;
        }
        ans = 0;
        /*for(i = 0;i <= m + 1;i ++)
        {
            for(j = 0;j <= m + 1;j ++)
                printf("%d ",dis[i][j]);
            printf("\n");
        }*/
        memset(vis,0,sizeof(vis));
        vis[0] = 1;
        dfs(0,l,0);
        printf("The best score is %d.\n",ans);
        if(t)
            printf("\n");
    }
    return 0;
}
//31MS	380K


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值