加载中…
个人资料
JosiahChiu
JosiahChiu
  • 博客等级:
  • 博客积分:0
  • 博客访问:7,096
  • 关注人气:87
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

HDU 2453 限制条件最短路

(2010-09-25 22:18:50)
标签:

hdu

2453

限制条件最短路

it

分类: 图论

题目描述:二维字符矩阵上有一船, ‘ ‘表示可走, ‘#’反之, ‘*’表示漩涡, 船每走"一格"消耗1单位A燃料, 船可以冲刺, 每次冲刺消耗perb单位的B燃料, 有两种冲刺方式, 一种是前方d个单位直线上没有’#'或’*', 直接冲到前方d格处, 另一种是前方临近格有漩涡, 冲刺进入此漩涡. 进漩涡只能靠冲刺, 现在A燃料无限, B燃料为b, 问最小消耗下的到达终点的"行动次数", 最小消耗的定义优先级有高到低分别是: 进入漩涡次数最少, A消耗最少, 行动次数最少.

解题报告:

对每个点的行动方案可行性做预处理, 然后用三维状态, 三维距离的Dijkstra做最短路. 其实把题目读懂, 做过二维Dijkstra的同学应该多少有点感觉了, 本题就是个三维状态的最短路:

dis[i][j][k]表示到i行j列冲刺了k次的最小耗费.

而这个"最小耗费"的定义也是三维的, 即:

1. 进入漩涡的次数.

2. A的消耗.

3. 行动次数.

而这个耗费大可不必用结构体来表示, 直接设INCU = 1000000, INCA = 1000, 其中INCU表示进一次漩涡的基数, INCA表示消耗一单位A的基数, 而行动次数的基数则是1, 这样它们的优先级也就由一个int型表示出来了. 然后设置冲刺次数上限为min{b/perb, r*c}即可(因为冲刺次数显然不会大于格子总数). 每次状态扩展的时候判断一下冲刺次数是否满足要求即可.

上文转自:http://www.answeror.com/archives/28350

限制条件最短路伪代码:

地图的状态找好,如dis[i][j][k],对应的有vst[i][j][k]

int judge(int i, int j, int k){return 最短路函数值;}

int dij()

{

         dis = Max, vst = false; heap;//优先队,按judge排

         dis[start_i][start_j][start_k] = 0;

         heap.push(start_i,  start_j, start_k);

         result = -1;

         while(!heap.empty())

         {

                   now = heap.top() ; heap.pop();

                   if (now == finish) {result = now; break;}

                   vst[now] = 1;

                   for(遍历所有从now的可达状态next)

                   {

                            if (!vst[next] && dis[now] + value < dis[next])

                            {

                                     dis[next] = dis[now] + value;

                                     if(!vst[next]) heap.push(next);

                            }

                   }

}

return result;

}

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define inf 0x7fffffff
#define A 1000000
#define B 1000
#define C 1
int d[20][20][400], vst[20][20][400], energy, per, n, m, dd, z, t;
int move[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
char g[21][21];
struct jeo
{
    int x, y, z;
    jeo(int x, int y, int z):x(x), y(y), z(z){}
    friend bool operator < (jeo a, jeo b){return d[a.x][a.y][a.z] > d[b.x][b.y][b.z];}
};
int judge(int a, int b, int c)
{
    return a * A + b * B + c * C;
}
int dij(int stax, int stay, int tox, int toy)
{
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            for(int k = 0; k <= z; k++) d[i][j][k] = inf, vst[i][j][k] = 0;
    d[stax][stay][0] = judge(0, 0, 0); priority_queue<jeo> heap;
    heap.push(jeo(stax, stay, 0)); int ans = -1;
    while(!heap.empty())
    {
        jeo tmp = heap.top(); heap.pop();
        if (tmp.x == tox && tmp.y == toy){ans = d[tmp.x][tmp.y][tmp.z] % 1000; break;}
        if (vst[tmp.x][tmp.y][tmp.z]) continue;
        vst[tmp.x][tmp.y][tmp.z] = 1;
        int a = d[tmp.x][tmp.y][tmp.z] / 1000000, b = (d[tmp.x][tmp.y][tmp.z] % 1000000) / 1000, c = d[tmp.x][tmp.y][tmp.z] % 1000;
        for(int i = 0; i < 4; i++)
        {
            int tmpa = tmp.x + move[i][0], tmpb = tmp.y + move[i][1];
            if (tmpa >= 0 && tmpa < n && tmpb >= 0 && tmpb < m && g[tmpa][tmpb] != '#')
            {
                if (g[tmpa][tmpb] == '*' && tmp.z + 1 <= z
                    && !vst[tmpa][tmpb][tmp.z + 1] && judge(a + 1, b + 1, c + 1) < d[tmpa][tmpb][tmp.z + 1])
                    d[tmpa][tmpb][tmp.z + 1] = judge(a + 1, b + 1, c + 1), heap.push(jeo(tmpa, tmpb, tmp.z + 1));
                else if (g[tmpa][tmpb] != '*' && !vst[tmpa][tmpb][tmp.z] && judge(a, b + 1, c + 1) < d[tmpa][tmpb][tmp.z])
                    d[tmpa][tmpb][tmp.z] = judge(a, b + 1, c + 1), heap.push(jeo(tmpa, tmpb, tmp.z));
            }
            bool flag = true;
            for(int j = 0, aa = tmp.x, bb = tmp.y; j <= dd; j++, aa += move[i][0], bb += move[i][1])
                if (j >= 1 && !(aa >= 0 && aa < n && bb >= 0 && bb < m && g[aa][bb] != '*' && g[aa][bb] != '#'))
                {flag = false; break;}
            if (flag && tmp.z + 1 <= z && !vst[tmp.x + move[i][0] * dd][tmp.y + move[i][1] * dd][tmp.z + 1]
                && judge(a, b + dd, c + 1) < d[tmp.x + move[i][0] * dd][tmp.y + move[i][1] * dd][tmp.z + 1])
            {
                d[tmp.x + move[i][0] * dd][tmp.y + move[i][1] * dd][tmp.z + 1] = judge(a, b + dd, c + 1);
                heap.push(jeo(tmp.x + move[i][0] * dd, tmp.y + move[i][1] * dd, tmp.z + 1));
            }
        }
    }
    return ans;
}
int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m); getchar();
        int stax, stay, tox, toy;
        for(int i = 0; i < n; i++)
        {
            gets(g[i]);
            for(int j = 0; j < m; j++)
                if (g[i][j] == 'S') stax = i, stay = j;
                else if (g[i][j] == 'E') tox = i, toy = j;
        }
        scanf("%d%d%d", &dd, &energy, &per);
        z = energy / per;
        int ans = dij(stax, stay, tox, toy);
        if (ans == -1) printf("can not reach!\n");
        else printf("%d\n", ans);
    }
    return 0;
}

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有