洛谷传送门
LOJ传送门
解析:
啊啊啊啊,这道题和网络流关系大吗?大吗?大吗?
就算是费用流来做实际上增广的过程也只被执行了一次,本质上仍然是最短路。
其实就是跑分层图的最短路,主要说说怎么构建分层图。
一看这个 k k k不好维护,它对路径的费用及贡献都十分的不可控,由于有一个强制消费机制的存在,我们根本没有办法令 k k k在状态中表示一个特定的东西。
那么我们令 d i s t [ ( i , j , k ) ] dist[(i,j,k)] dist[(i,j,k)]表示当前在 ( i , j ) (i,j) (i,j)这个位置,已经消耗的步数为 k k k的最小花费。
那么根据这个点是空地还是加油站都够非常方便的写出状态转移的式子了,按照式子建图跑最短路就好了。
费用流就是在最短路的基础上将源点的流量限制为1,边权改为费用,然后求最小费用。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=300005,M=1000006;
int last[N],nxt[M],to[M],ecnt;
int w[M];
inline void addedge(int u,int v,int val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
}
int n,k,a,b,c;
#define pos(x,y,h) (n*n*(h-1)+n*(x-1)+y)
int dist[N];
bool vis[N];
set<pair<int,int> > q;
inline void dijkstra(){
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
dist[pos(1,1,1)]=0;
q.insert(make_pair(0,pos(1,1,1)));
while(!q.empty()){
int u=q.begin()->second;
q.erase(q.begin());
if(vis[u])continue;
vis[u]=true;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
if(dist[v]>dist[u]+w[e]){
q.erase(make_pair(dist[v],v));
dist[v]=dist[u]+w[e];
q.insert(make_pair(dist[v],v));
}
}
}
}
signed main(){
n=getint();
k=getint();
a=getint();
b=getint();
c=getint();
for(int re i=1;i<=n;++i){
for(int re j=1;j<=n;++j){
int f=getint();
for(int re h=1;h<=k+1;++h){
addedge(pos(i,j,h),pos(i,j,h+1),0);
}
if(f){
addedge(pos(i,j,k+1),pos(i,j,1),a);
if(i<n)addedge(pos(i,j,1),pos(i+1,j,2),0);
if(j<n)addedge(pos(i,j,1),pos(i,j+1,2),0);
if(i>1)addedge(pos(i,j,1),pos(i-1,j,2),b);
if(j>1)addedge(pos(i,j,1),pos(i,j-1,2),b);
}
else{
for(int re h=1;h<=k;++h){
if(i<n)addedge(pos(i,j,h),pos(i+1,j,h+1),0);
if(j<n)addedge(pos(i,j,h),pos(i,j+1,h+1),0);
if(i>1)addedge(pos(i,j,h),pos(i-1,j,h+1),b);
if(j>1)addedge(pos(i,j,h),pos(i,j-1,h+1),b);
}
for(int re h=2;h<=k+1;++h)addedge(pos(i,j,h),pos(i,j,1),a+c);
}
}
}
dijkstra();
int ans=0x3f3f3f3f;
for(int re i=1;i<=k+1;++i)ans=min(ans,dist[pos(n,n,i)]);
cout<<ans;
return 0;
}