질문은 다음 세 가지 조건을 충족해야합니다.
1 : 자동차가 그리드 가장자리를 통과 할 때 X 좌표 또는 Y 좌표가 감소하면 수수료 B를 지불해야하며 그렇지 않으면 수수료가 무료입니다.
2 : 차량이 주행 중 오일 디포를 만났을 때, 충전하고 주 유료 A를 지불해야합니다.
3 : 필요할 때 그리드 지점에 오일 디포를 추가하고 추가 오일 디포 비용 C (급유 비용 A 제외)를 지불 할 수 있습니다.
4 : 자동차는 그리드의 가장자리를 따라서 만 운전할 수 있으며 연료로 채워진 후 K 그리드 가장자리를 운전할 수 있습니다.
아이디어 :이 질문은 Luogu Network Stream 24 질문에 있지만 해결책은 모두 가장 짧습니다. 지도 구성에 대한 최단 경로입니다. 비용 계층화에 따르면 전체 오일은 k 번만 갈 수 있으므로 k + 1 레이어로 나누고 0 번째 레이어는 전체 오일을 나타내고 첫 번째 레이어는 오일 소비량의 한 단위를 나타냅니다.
첫 번째 조건 :이 레이어의 방향 가장자리를 상위 레이어의 인접한 네 방향에 연결합니다. x 또는 y 좌표가 감소하면 가장자리 가중치는 b이고 그렇지 않으면 가장자리 가중치는 0입니다.
두 번째 조건의 경우 : 오일 디포를 만날 때 급유가 필수이므로 첫 번째 레이어 이상은 가장자리를 첫 번째 레이어에 연결하고 가장자리 무게는 A입니다. 이때 0 번째 레이어와 첫 번째 레이어도 연결해야합니다. 이 지점을 통과하면 다음 단계가 다른 레이어가 아닌 첫 번째 레이어 만 될 수 있기 때문입니다.
세 번째 조건의 경우 :이 지점이 석유 저장소가 아닌 경우 각 레이어는 가장자리를 첫 번째 레이어에 연결하고 가장자리 가중치는 a + c입니다. 즉,이 지점에 새 석유 저장소가 건설되었음을 의미합니다.
네 번째 조건 : 계층화 된지도 작성
#include <bits/stdc++.h>
#define ll long long
#define pi pair<int,int>
#define mk make_pair
#define pb push_back
using namespace std;
const int maxn = 1e6+10;
int d[maxn],vis[maxn],n;
vector<pi>G[maxn];
int id(int x,int y,int k)
{
return n*n*k + ((x-1)*n) + y;
}
void add(int u,int v,int w)
{
G[u].pb(mk(v,w));
}
void dij(int s)
{
priority_queue<pi>q;
memset(d,0x3f,sizeof(d));
d[s] = 0;
q.push(mk(0,s));
while(q.size())
{
int u = q.top().second;
q.pop();
if(vis[u])continue;
vis[u] = 1;
for(int i=0;i<G[u].size();i++)
{
int v = G[u][i].first;
int w = G[u][i].second;
if(d[v] > d[u] + w)
{
d[v] = d[u] + w;
q.push(mk(-d[v],v));
}
}
}
}
int main()
{
int k,a,b,c;
scanf("%d%d%d%d%d",&n,&k,&a,&b,&c);
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
{
int ddd;
scanf("%d",&ddd);
if(ddd == 1)
{
for(int i=1;i<=k;i++) {
add(id(x,y,i) , id(x,y,0) , a);
}
if(x+1 <= n) add(id(x, y, 0), id(x+1, y, 1), 0);
if(x-1 >= 1) add(id(x, y, 0), id(x-1, y, 1), b);
if(y+1 <= n) add(id(x, y, 0), id(x, y+1, 1), 0);
if(y-1 >= 1) add(id(x, y, 0), id(x, y-1, 1), b);
}
else
{
for(int i=1;i<=k;i++)
{
add(id(x,y,k), id(x,y,0), a+c);
if(x+1 <= n) add(id(x, y, i-1), id(x+1, y, i), 0);
if(x-1 >= 1) add(id(x, y, i-1), id(x-1, y, i), b);
if(y+1 <= n) add(id(x, y, i-1), id(x, y+1, i), 0);
if(y-1 >= 1) add(id(x, y, i-1), id(x, y-1, i), b);
}
}
}
int s = id(1,1,0);
dij(s);
int ans = 0x3f3f3f3f;
for(int i=0;i<=k;i++)ans = min(ans , d[id(n,n,i)]);
printf("%d\n",ans);
return 0;
}