洛谷 P4009 汽车加油行驶问题 题解

网络流24题?费用流?不存在的

tag都是骗人的

首先看题,仔细想想,这不就是一个最短路吗?

从 (1,1) 往 (n,n) 跑最短路,以 dis[x][y][res] 来记录当位于 (x,y) 时还能再跑 res 条边的最小花费

每次扩展节点的时候更新加油的花费, 注意当(x,y) 有油库时强制加油,没有时可不加

最后 for i from 0 to k 统计 dis[n][n][i] 的最小值,即为答案

实现细节见代码

Tips:代码中含有 __gnu_pbds::priority_queue 与 std::tuple ,可能引起强烈不适,请谨慎食用

 1 #ifndef ONLINE_JUDGE
 2 #define _EXT_ENC_FILEBUF_H 1
 3 #define _EXT_CODECVT_SPECIALIZATIONS_H 1
 4 #endif // ONLINE_JUDGE
 5 #include<bits/stdc++.h>
 6 #include<bits/extc++.h>
 7 using namespace std;
 8 typedef tuple<int,int,int> pit; // x, y, res
 9 constexpr int fx[5][2]={{0,0},{1,0},{0,-1},{-1,0},{0,1}};
10 int n,K,A,B,C,ans=numeric_limits<int>::max();
11 int dis[150][150][20];
12 bool in[150][150][20],oil[150][150];
13 struct cmp{bool operator()(pit a,pit b)
14 {return dis[get<0>(a)][get<1>(a)][get<2>(a)]>dis[get<0>(b)][get<1>(b)][get<2>(b)];}};
15 __gnu_pbds::priority_queue<pit,cmp,__gnu_pbds::pairing_heap_tag> q;
16 void SPFA();
17 int main()
18 {
19     scanf("%d%d%d%d%d",&n,&K,&A,&B,&C);
20     for(int i=1;i<=n;i++)
21         for(int j=1;j<=n;j++){
22             int col;
23             scanf("%d",&col);
24             oil[i][j]=(col==1);
25         }
26     SPFA();
27     for(int i=0;i<=K;i++)
28         ans=min(ans,dis[n][n][i]);
29     printf("%d",ans);
30 }
31 void SPFA()
32 {
33     memset(dis,0x7f,sizeof(dis));
34     dis[1][1][K]=0;
35     in[1][1][K]=true;
36     q.push(make_tuple(1,1,K));
37     while(!q.empty()){
38         pit now=q.top();
39         q.pop();
40         int x=get<0>(now),y=get<1>(now),res=get<2>(now);
41         in[x][y][res]=false;
42         if(oil[x][y]&&res!=K){
43             if(dis[x][y][K]>dis[x][y][res]+A){
44                 dis[x][y][K]=dis[x][y][res]+A;
45                 if(!in[x][y][K]){
46                     q.push(make_tuple(x,y,K));
47                     in[x][y][K]=true;
48                 }
49             }
50             continue;
51         }
52         if(dis[x][y][K]>dis[x][y][res]+A+C){
53             dis[x][y][K]=dis[x][y][res]+A+C;
54             if(!in[x][y][K]){
55                 q.push(make_tuple(x,y,K));
56                 in[x][y][K]=true;
57             }
58         }
59         if(res<=0) continue;
60         for(int i=1;i<=4;i++){
61             int xi=x+fx[i][0],yi=y+fx[i][1];
62             if(xi<1||xi>n||yi<1||yi>n) continue;
63             int cost=(xi<x||yi<y)?B:0;
64             if(dis[xi][yi][res-1]>dis[x][y][res]+cost){
65                 dis[xi][yi][res-1]=dis[x][y][res]+cost;
66                 if(!in[xi][yi][res-1]){
67                     q.push(make_tuple(xi,yi,res-1));
68                     in[xi][yi][res-1]=true;
69                 }
70             }
71         }
72     }
73 }
View Code

猜你喜欢

转载自www.cnblogs.com/Sepia/p/10121810.html
今日推荐