hdu 1044 Collect More Jewels 搜索

hdu 1044 Collect More Jewels 搜索
//hdu 1044 Collect More Jewels
//搜索
//题意:起点 '@' 终点 '<' 宝石 'A' ~ 'J',在一定时间内
//从起点到终点,且求出能得到最多价值是多少

//思路:先用广搜求出起点、终点即所有宝石之间的最短距离
//然后深搜

#include <stdio.h>
#include <string.h>


#define N 55
#define INF 1<<30
#define eps 1e-5

const int dir[2][4] = {0, -1, 0, 1, -1, 0, 1, 0};

struct NODE
{
    int x, y;
}node[20], que[N*N];

int col, row, limit, n_jewel, ans;
int jewel[15], step[N][N];    //step记录广搜中到某个结点的步数
int dis[20][20];
char map[N][N];
bool vis[20];

bool no_overmap(int x, int y)
{
    return (x >= 0 && x < col && y >= 0 && y < row);
}

int get_index(int x, int y)
{
    if(map[x][y] == '@')
        return n_jewel + 1;
    else if(map[x][y] == '<')
        return n_jewel;
    else
        return map[x][y] - 'A';
}

void bfs(int root)   //breadth first search
{
    for(int i = 0; i < col; ++i)
        for(int j = 0; j < row; ++j)
            step[i][j] = 0;
    int head = 0, tail = 0;
    que[++head].x = node[root].x;
    que[head].y = node[root].y;
    while(tail < head)
    {
        int x = que[++tail].x, y = que[tail].y;
        for(int i = 0; i < 4; ++i)
        {
            int nx = x + dir[0][i], ny = y + dir[1][i];
            if(no_overmap(nx, ny) && step[nx][ny] == 0 && map[nx][ny] != '*' &&
               (nx != node[root].x || ny != node[root].y))
            {
                step[nx][ny] = step[x][y] + 1;
                if(map[nx][ny] != '.')
                {
                    int to = get_index(nx, ny);
                    dis[root][to] = step[nx][ny];
                }
                que[++head].x = nx;
                que[head].y = ny;
            }
        }
    }
}

void dfs(int root, int val, int time)
{
    //记得判断当前点即root到终点的时间,否则超时,有的话也要900多毫秒才过
    if(time + dis[root][n_jewel] > limit)
        return;
    if(root == n_jewel)
    {
        ans = ans > val ? ans : val;
        return;
    }
    //由于最短路之前都求过了,dfs只要判断该点要或不要就可以了
    //则列举这些点的排列肯定有一种是答案,当前点可以要或不要
    for(int i = 0; i <= n_jewel; ++i)
    {
        if(vis[i] == false && time + dis[root][i] <= limit)
        {
            vis[i] = true;
            dfs(i, val + jewel[i], time + dis[root][i]);
            vis[i] = false;
        }
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    int n_case;
    scanf("%d", &n_case);
    for(int ca = 1; ca <= n_case; ++ca)
    {
        printf("Case %d:\n", ca);
        scanf("%d%d%d%d", &row, &col, &limit, &n_jewel);
        for(int i = 0; i < n_jewel; ++i)
            scanf("%d", &jewel[i]);
        for(int i = 0; i < col; ++i)
        {
            getchar();
            for(int j = 0; j < row; ++j)
            {
                map[i][j] = getchar();
                if(map[i][j] == '@')
                {
                    node[n_jewel + 1].x = i;
                    node[n_jewel + 1].y = j;
                    jewel[n_jewel + 1] = 0;
                }
                if(map[i][j] == '<')
                {
                    node[n_jewel].x = i;
                    node[n_jewel].y = j;
                    jewel[n_jewel] = 0;
                }
                if(map[i][j] >= 'A' && map[i][j] <= 'J')
                {
                    node[map[i][j] - 'A'].x = i;
                    node[map[i][j] - 'A'].y = j;
                }
            }
        }

        for(int i = 0; i <= n_jewel + 1; ++i)
            for(int j = 0; j < i; ++j)
                dis[i][j] = dis[j][i] = INF;

        bfs(n_jewel + 1);
        if(dis[n_jewel + 1][n_jewel] > limit)
        {
            printf("Impossible\n\n");
            continue;
        }
        
        for(int i = 0; i <= n_jewel; ++i)   //求i到各点的最短距离
            bfs(i);

        for(int i = 0; i <= n_jewel + 1; ++i)
            vis[i] = false;
            
        ans = 0;
        dfs(n_jewel + 1, 0, 0);
        printf("The best score is %d.\n", ans);
        if(ca != n_case)
            puts("");
    }
    return 0;
}

 

posted @ 2012-07-18 10:09  gabo  阅读(239)  评论(0编辑  收藏  举报