网络流24题—— 汽车加油行驶问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/82425836

题目链接:https://www.luogu.org/problemnew/show/P4009

【问题分析】

分层图最短路径问题。

【建模方法】

按照油箱中剩余油量建立K层图,汽车在地图上点i,剩余油量为l时,对应点为<i,l>。

1、如果油箱不满(l<K),点i为油库点,从<i,l>到<i.top>建立一条权值为A的有向边。
2、如果油箱不满(l<K),点i不为油库点,从<i,l>到<i.top>建立一条权值为A+C的有向边。
3、如果油箱不为空,i不为油库点,每层l从<i.l>到<j.l-1>建立一条权值为0的有向边,其中j为i的右边或下边相邻的一个顶点;从<i.l>到<j.l-1>建立一条权值为B的有向边,其中j为i的左边或上边相邻的一个顶点。
4、如果油箱不为空,i为油库点,从<i.K>到<j.K-1>建立一条权值为0的有向边,其中j为i的右边或下边相邻的一个顶点;从<i.K>到<j.K-1>建立一条权值为B的有向边,其中j为i的左边或上边相邻的一个顶点。

求从<(1,1),K>的单源最短路径,到达目标的最小费用就是Min{dist[<(N,N),k>] | 0 <= k <= K }

感觉第4条别管油箱空不空都需要建边,因为i为油库点已经加满油了

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4000005;
const int INF = 0x3f3f3f3f;
int n,k,a,b,c;
int is[105][105];
int to[4][2] = {1,0,0,1,-1,0,0,-1};
int tot,head[MAXN];
struct node
{
    int to,next,w;
}edge[MAXN];
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v,int w)
{
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}
struct HeapNode
{
	int u,d;
	HeapNode(){}
	HeapNode(int _u,int _d)
	{
	    u = _u;
	    d = _d;
	}
	bool operator < (const HeapNode& rhs) const
	{
		return d > rhs.d;
	}
};
int dis[MAXN];
bool vis[MAXN];
void dijkstra(int s)
{
    struct HeapNode t;
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    priority_queue<HeapNode> pq;
    pq.push(HeapNode(s,0));
    dis[s] = 0;
    while(!pq.empty()) {
        t = pq.top();
        pq.pop();
        if(vis[t.u]) continue;
        vis[t.u] = true;
        int u = t.u;
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int to = edge[i].to;
            if(dis[to] > dis[u] + edge[i].w) {
                dis[to] = dis[u] + edge[i].w;
                pq.push(HeapNode(to,dis[to]));
            }
        }
    }
}
int Point(int x,int y,int f)
{
    return f * n * n + (x - 1) * n + y;
}
int main(void)
{
    scanf("%d %d %d %d %d",&n,&k,&a,&b,&c);
    init();
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            scanf("%d",&is[i][j]);
        }
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            for(int f = 0; f <= k; f++) {
                int C = is[i][j] ? a : a + c;
                if(f < k) AddEdge(Point(i,j,f),Point(i,j,k),C);
                for(int q = 0; q < 4; q++) {
                    int tx = i + to[q][0];
                    int ty = j + to[q][1];
                    if(tx <= 0 || ty <= 0 || tx > n || ty > n) continue;
                    C = q < 2 ? 0 : b;
                    if(!is[i][j] && f > 0) AddEdge(Point(i,j,f),Point(tx,ty,f - 1),C);
                    else if(is[i][j]) AddEdge(Point(i,j,k),Point(tx,ty,k - 1),C);
                }
            }
        }
    }
    dijkstra(Point(1,1,k));
    int ans = 10000000;
    for(int i = 0; i <= k; i++) {
        ans = min(ans,dis[Point(n,n,i)]);
    }
    printf("%d\n",ans);
    return 0;
}

直接BFS也能过,只在油量为空并且不能加油的情况下才建立加油厂

#include <bits/stdc++.h>
using namespace std;
int cost[105][105][15],mp[105][105],vis[105][105][15];
int to[8][2] = {{0,1},{1,0},{0,-1},{-1,0}};
int n,k,a,b,c;
struct node
{
    int x,y;
    int f,cost;
    node(){}
    node(int _x,int _y,int _cost,int _f)
    {
        x = _x;
        y = _y;
        cost = _cost;
        f = _f;
    }
    bool operator <(const struct node& a) const
    {
        return cost > a.cost;
    }
};
int ans;
void BFS()
{
    struct node t;
    cost[1][1][k] = 0;
    priority_queue<node> pq;
    pq.push(node(1,1,0,k));
    while(!pq.empty()) {
        t = pq.top();
        pq.pop();
        if(vis[t.x][t.y][t.f]) continue;
        vis[t.x][t.y][t.f] = 1;
        for(int i = 0; i < 4; i++) {
            int tx = t.x + to[i][0];
            int ty = t.y + to[i][1];
            int tc,tf;
            if(tx < 1 || ty < 1 || tx > n || ty > n) continue;
            if(tx < t.x || ty < t.y) tc = t.cost + b;
            else tc = t.cost;
            if(tx == n && ty == n) {
                ans = tc;
                return;
            }
            tf = t.f - 1;
            if(mp[tx][ty]) {
                tf = k;
                tc += a;
            }
            if(tf == 0) {
                tf = k;
                tc += (c + a);
            }
            pq.push(node(tx,ty,tc,tf));
        }
    }
}
int main(void)
{
    scanf("%d %d %d %d %d",&n,&k,&a,&b,&c);
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            scanf("%d",&mp[i][j]);
        }
    }
    BFS();
    printf("%d\n",ans);
    return 0;
}


 

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/82425836
今日推荐