ZOJ 3611 BFS+状态压缩

来源:互联网 发布:样本数据的相关系数 编辑:程序博客网 时间:2024/05/02 21:22

问题描述

On the way to the Dragon’s Castle, there is an Ice Valley. Now Lott wants to pass through the Ice Valley. While in the Ice Valley, there was a lot of treasure, and the treasure can be helpful to Lott, so Lott wants to get as many treasure as he can.

Now, Lott has reached the Ice Valley, and he finds that the Ice Valley is made up of n*m blocks. And on the blocks there are different signs. Lott has been told by friendly NPC that the meaning of each signs:

The meaning of each signs:
Nothing: The block is an empty ground, you step on it and then you can choose to go up, down, left, right as you like. However the number of this kind of block is very few no more than 100.
Arrow: The block has magic power, you step on it and you have to go to the next block in the same direction as the arrow.
Wall: The block is a wall, and you can never step on it.
Box: The block has a box with treasure, you step on it and you can open the box to get the treasure, then, you can go up, down, left, right as you like. The number of the box in the valley is always no greater than 10.
Hole: The block is a trap, and you will die if you step on it.

Now, Lott starts at the entrance of the valley x1, y1. He wants to get to the exit at the position of x2, y2. And at the same time, Lott wants to get the most treasure he can. The entrance and the exit are both signed nothing. The entrance and the exit can be the same positions.

Now, we assume that each movement from one block to another costs 1 second and each opening of one box spends 2 seconds, and we want to know the minimum time Lott uses to pass through the valley with the most treasure.

输入

There are multiple cases.

In each cases, the first line contains two integers n , m. (1<=n<=500 , 1<=m<=500)

Then n lines with m characters describing the valley. And ‘0’ represents nothing; ‘L’,’U’,’D’,’R’ represents arrow with the direction of left, up, down, right; ‘W’ represents a wall; ‘$’ represents a box with treasure; ‘#’ represents the trap hole.

Then the last line with four integer x1, y1, x2, y2. (1<=x1<=500 , 1<=y1<=500 , 1<=x2<=500 , 1<=y2<=500)

输出

Of each case, output one line with one integer representing the minimum time Lott will use, if he cannot pass through the valley, output -1.

样例输入

5 5
DL0RDWDWDDLLL
D#DWU
RURR0
1 3 5 5
5 5
0RRRD
UW#D  
UD0UD  
U#
WD
ULLLL
1 1 3 3

样例输出

14
-1

*【题意】:

给定一张n*m的图,图上每个点有如下情况:
L,R,D,U:代表在该点上只能往它已经给定的方向前进。

,W:不能走到该点。

$:走到该点,可以花两分钟得到一分值,然后可以从该点向任意方向走。
0:走到该点后可以向任意方向走。
然后给你起点和终点坐标,问是否能从起点走到终点,如果能,求出可获得的最大分值以及与之对应达到该最大分值所需的的最小时间花
费。(其中起点和终点坐标可以相同)
【知识点】:
BFS+状态压缩
【题解】:
我觉得超级棒的题!真心感觉涨姿势了。
几个关键处理:
1、对图的转换,重新建模。先取出所有可以往任意方向行走的点并为之标号(因为这两者加起来的和也只是区区110而已)。然后找离该
点最近的能自由方向行走的点并求其时间,然后连边(时间为该边的权值)。(邻接矩阵就这样变成一个小巧的邻接表了)
2、状态转移部分。用dp[u][state]记录当从起点走到点u(这里的u指的是转换后得到的邻接表的点)得到财宝的状态为state时所需要的
最小时间花费。显然有初始状态dp[st][0] = 0,st为起点,其它状态设为不可达。利用bfs求出dp的解。然后在终点处找状态中1最多并且
在终点时该状态可达,对应的值即为答案。若在终点处所有状态都不可达,则无解。
【代码】:*

#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <cstdio>#include <iomanip>#include <string>#include <vector>#include <cstring>#include <sstream>#include <iostream>#include <fstream>#include <algorithm>#include <bitset>#include <climits>#include <ostream>#include <ios>#include <cstdlib>using namespace std;#define wh while#define inf (int)(~0u/2)#define FOR(i, n) for(int i = 0; i < n; i++)#define FOR1(i, n) for(int i = 1; i < n; i++)#define FOR2(i, n) for(int i = 0; i <= n; i++)#define REP(i,n) for(int i = 1; i <= n; i++)#define FORI(it,n) for(typeof(n.begin()) it = n.begin(); it != n.end(); it++)#define sf scanf#define pf printf#define frs first#define sec second#define psh push_back#define mkp make_pair#define PB(x) push_back(x)#define MP(x, y) make_pair(x, y)#define clr(abc,z) memset(abc,z,sizeof(abc))#define lt(v) v << 1#define rt(v) v << 1 | 1#define mid ((l + r) >> 1)#define lson l, mid, v << 1#define rson mid + 1, r, v << 1 | 1#define fre freopen("1.txt", "r", stdin)typedef long long LL;typedef long double LD;const int maxn = 550;const int bt = 2100;const int smaxn = 220;const int INF = 1061109567;int dp[smaxn][bt];bool inq[smaxn][bt];struct EDGE{    int v, w;};struct NODE{    int id; int state;    NODE(){}    NODE(int x, int y){        id = x; state = y;    }};int dx[] = {0, 1, 0, -1};int dy[] = {1, 0, -1, 0};int n, m; int num1, num2;vector<EDGE> G[maxn];int stx, sty, edx, edy;char s[maxn][maxn];int id[maxn][maxn];bool vis[maxn][maxn];void init(){    clr(id, -1);    num1 = num2 = 0;    FOR(i, smaxn) G[i].clear();    FOR(i, n)        sf("%s", s[i]);    sf("%d%d%d%d", &stx, &sty, &edx, &edy);    stx--; sty--; edx--; edy--;}bool isOK(int x, int y){    if(x >= 0 && x < n && y >= 0 && y < m       && s[x][y] != 'W' && s[x][y] != '#')        return true;    return false;}void add(int u, int v, int w){    EDGE tmp; tmp.v = v; tmp.w = w;    G[u].PB(tmp);}int getnear(int x, int y, int& t){    clr(vis, 0);    wh(s[x][y] != '0' && s[x][y] != '$'){        t++;        if(s[x][y] == 'L') y--;        else if(s[x][y] == 'R') y++;        else if(s[x][y] == 'U') x--;        else if(s[x][y] == 'D') x++;        if(!isOK(x, y)) return -1;        if(vis[x][y]) return -1;        vis[x][y] = true;    }    return id[x][y];}int getlong1(int x){    int ans = 0;    wh(x){        if(x & 1) ans++;        x >>= 1;    }    return ans;}int main(){    wh(sf("%d%d", &n, &m) != EOF){        init();        FOR(i, n) FOR(j, m)            if(s[i][j] == '$') id[i][j] = num1++;        num2 = num1;        FOR(i, n) FOR(j, m)            if(s[i][j] == '0') id[i][j] = num2++;        FOR(i, n) FOR(j, m)            if(id[i][j] != -1){                int u = id[i][j];                FOR(k, 4){                    int tx = i + dx[k]; int ty = j + dy[k];                    int tm = 1;                    if(isOK(tx, ty)){                        int v = getnear(tx, ty, tm);                        if(v != -1)                            add(u, v, tm);                    }                }            }        int idst = id[stx][sty]; int ided = id[edx][edy];        queue<NODE> Q;        wh(!Q.empty()) Q.pop(); Q.push(NODE(idst, 0));        clr(dp, 0x3f); clr(inq, 0);        dp[idst][0] = 0; inq[idst][0] = true;        wh(!Q.empty()){            int u = Q.front().id;            int state0 = Q.front().state; Q.pop();            inq[u][state0] = false;            int ns, nt, nv;            FOR(i, (int)G[u].size()){                ns = state0; nt = dp[u][state0];                nv = G[u][i].v; nt += G[u][i].w;                if(nv < num1 && (((1 << nv) & ns) == 0)){                    nt += 2; ns |= (1 << nv);                }                if(dp[nv][ns] > nt){                    dp[nv][ns] = nt;                    if(!inq[nv][ns]){                        Q.push(NODE(nv, ns));                        inq[nv][ns] = true;                    }                }            }        }        int ans = INF, ft = -1;        FOR(i, (1 << num1)){            int btlong = getlong1(i);            if(btlong > ft && dp[ided][i] < INF){                ans = dp[ided][i]; ft = btlong;            }        }        if(ans == INF) pf("-1\n");        else pf("%d\n", ans);    }}
0 0
原创粉丝点击