HDU 1044 Collect More Jewels

题目链接:Collect More Jewels

解题思路:一看又是简单的广搜,还以为水题,所以简单敲了一发,T了。思佳说用BFS + DFS。算了算总状态数50*50*2^10 = 256W, 一共10组,而且还有它给出的时间有可能很多,这样所有宝物都能捡到还能瞎逛。就是宝物逝去序列的所有组合。所以应该先处理两两宝物之间的最短路,和起点到所有宝物的最短路,终点到所有宝物的最短路,全部用BFS跑一遍,然后再对所有宝物进行DFS找到最大的价值,要注意如果已经找到最大值就要直接退出,否则会TLE。减枝很重要。


#include<cstdio>
#include<cstring>
#include<queue>
#define MAX 55
#define MAXN 20
#define INF 0x5f5f5f5f

using namespace std;

struct node{
    int x, y, s;
    node(){}
    node(int xx, int yy, int ss){
        x = xx, y = yy, s = ss;
    }
};

int n, m, l, k;
int g[MAX][MAX], dis[MAXN][MAXN];
bool v[MAX][MAX], vis[MAXN];
int jv[MAXN], jx[MAXN], jy[MAXN];
int ans, sx, sy, ex, ey, sum;
int dir[4][2] = {1,0,-1,0,0,1,0,-1};

void init(){
    for(int i = 0; i < k; i++){
        for(int j = 0; j < k; j++){
            dis[i][j] = i == j ? 0 : INF;
        }
    }
    ans = -1;
    memset(vis, 0, sizeof(vis));
}

int getC(char c){
    if(c == '@')    return 0;
    if(c == '<')    return k - 1;
    if(c >= 'A' && c <= 'J')    return c - 'A' + 1;
    return -1;
}

void bfs(int x, int y, int idx){
    int i, j;
    queue<node> mq;
    memset(v, false, sizeof(v));
    v[x][y] = true;
    mq.push(node(x, y, 0));
    while(!mq.empty()){

        node s = mq.front();
        //printf("idx = %d %d %d %d\n", idx, s.x, s.y, s.s);
        mq.pop();
        for(i = 0; i < 4; i++){
            int xx = s.x + dir[i][0];
            int yy = s.y + dir[i][1];
            int ss = s.s + 1;
            if(xx >= 0 && xx < n && yy >= 0 && yy < m && !v[xx][yy] && g[xx][yy] != '*'){
                v[xx][yy] = true;
                if(getC(g[xx][yy]) != -1){
                    dis[getC(g[xx][yy])][idx] = ss;
                    dis[idx][getC(g[xx][yy])] = ss;
                }
                mq.push(node(xx, yy, ss));
            }
        }

    }
}



void dfs(int now, int d, int v, int pre){
    //printf("%d %d %d %d\n",pre, now, d, v);
    int i, j;
    if(d > l || sum == ans) return;
    if(now == k - 1 && v > ans){
        ans = v;
    }
    for(i = 0; i < k; i++){
        if(dis[now][i] == INF || vis[i])    continue;
        vis[i] = true;
        dfs(i, d + dis[now][i], v + jv[i], now);
        vis[i] = false;
    }
}

int main(){
    int i, j, t, tot = 0;
    //#ifndef ONLINE_JUDGE
    //freopen("1.in", "r", stdin);
    //freopen("1.out", "w", stdout);
    //#endif // ONLINE_JUDGE

    scanf("%d", &t);
    while(t--){
        if(tot++)   printf("\n");
        scanf("%d%d%d%d", &m, &n, &l, &k);
        sum = 0;
        for(i = 1; i <= k; i++){
            scanf("%d", &jv[i]);
            sum += jv[i];
        }
        jv[0] = jv[k + 1] = 0;
        k += 2;
        init();
        for(i = 0; i < n; i++){
            getchar();
            for(j = 0; j < m; j++){
                g[i][j] = getchar();
                if(g[i][j] == '@'){
                    jx[0] = i, jy[0] = j;
                }
                if(g[i][j] == '<'){
                    jx[k - 1] = i, jy[k - 1] = j;
                }
                if(g[i][j] <= 'J' && g[i][j] >= 'A'){
                    jx[g[i][j] + 1 - 'A'] = i;
                    jy[g[i][j] + 1 - 'A'] = j;
                }
            }
        }
        for(i = 0; i < k - 1; i++){
            bfs(jx[i], jy[i], i);
        }
        printf("Case %d:\n", tot);
        if(dis[0][k - 1] > l){
            puts("Impossible");
            continue;
        }
        vis[0] = true;
        dfs(0, 0, 0, -1);
        if(ans == -1){
            puts("Impossible");
        }
        else{
            printf("The best score is %d.\n", ans);
        }
    }
    return 0;
}


你可能感兴趣的:(DFS,bfs,好题)