Submission #248963

#TimeUsernameProblemLanguageResultExecution timeMemory
248963pit4hSoccer (JOI17_soccer)C++14
100 / 100
1567 ms10504 KiB
#include<iostream>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>

using ll = long long;
using namespace std;

const int H=503, N=1e5+2;
const ll INF = 5e12+1;
int h, w, n, s[N], t[N];
ll a, b, c;
bool player[H][H];

ll closest[H][H];
ll minX[H][H], maxX[H][H];

bool vis[H][H];
ll dist[H][H];
ll minimal[H];

struct Obj {
	ll d;
	int x, y;
	
	bool operator<(Obj o) const{
		return d > o.d;	
	}
};

Obj Find_best() {
	ll mini = INF;
	int cord=-1;
	for(int i=1; i<=h; ++i) {
		if(mini > minimal[i]) {
			mini = minimal[i];
			cord = i;
		}
	}
	Obj res;
	res.d = mini;
	res.x = cord;
	res.y = -1;
	if(mini == INF) return res;
	for(int i=1; i<=w; ++i) {
		if(!vis[cord][i] && dist[cord][i] == minimal[cord]) {
			res.y=i;
			break;
		}
	}
	vis[res.x][res.y] = 1;
	minimal[cord] = INF;
	for(int i=1; i<=w; ++i) {
		if(!vis[cord][i]) {
			minimal[cord] = min(minimal[cord], dist[cord][i]);
		}
	}
	return res;
}

vector<int> moveX = {0, 0, 1, -1}, moveY = {1, -1, 0, 0};

bool inside(int x, int y) {
	if(x>=1 && x<=h && y>=1 && y<=w) return true;
	return false;
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	cin>>h>>w;
	cin>>a>>b>>c;
	cin>>n;
	h++;
	w++;

	for(int i=0; i<n; ++i) { 
		cin>>s[i]>>t[i];	
		s[i]++;
		t[i]++;
		player[s[i]][t[i]] = 1;
	}

	for(int i=1; i<=w; ++i) {
		maxX[0][i] = -INF;
	}
	for(int x=1; x<=h; ++x) {
		for(int y=1; y<=w; ++y) {
			if(player[x][y]) maxX[x][y] = x;
			else maxX[x][y] = maxX[x-1][y];
		}
	}

	for(int i=1; i<=w; ++i) {	
		minX[h+1][i] = INF;
	}
	for(int x=h; x>=1; --x) {
		for(int y=1; y<=w; ++y) {
			if(player[x][y]) minX[x][y] = x;
			else minX[x][y] = minX[x+1][y];
		}
	}

	for(int x=1; x<=h; ++x) {
		for(int y=1; y<=w; ++y) {
			closest[x][y] = INF;
			for(int i=1; i<=w; ++i) {
				closest[x][y] = min(closest[x][y], abs(y-i) + min( x - maxX[x][i], minX[x][i] - x));
			}
		}
	}

	for(int i=1; i<=h; ++i) {
		for(int j=1; j<=w; ++j) {
			dist[i][j] = INF;
		}
	}
	
	dist[s[0]][t[0]] = 0;

	for(int i=1; i<=h; ++i) {
		minimal[i] = INF;
	}
	minimal[s[0]] = 0;
	while(true) {
		auto cur = Find_best();
		ll d = cur.d;
		if(d==INF) break;
		int x = cur.x;
		int y = cur.y;
		// C
		for(int i=0; i<4; ++i) {
			int nx = x+moveX[i], ny = y+moveY[i];
			if(inside(nx, ny) && d + c < dist[nx][ny]) {
				dist[nx][ny] = d + c;
				minimal[nx] = min(minimal[nx], dist[nx][ny]);
			}
		}

		//Ax + B
		for(int i=0; i<4; ++i) {
			for(int p=1; p<=max(h, w); ++p) {
				int nx = x+p*moveX[i], ny = y+p*moveY[i];
				if(!inside(nx, ny)) break;
				ll nd = d + a*p + b + c * closest[nx][ny];
				if(nd < dist[nx][ny]) {
					dist[nx][ny] = nd;
					minimal[nx] = min(minimal[nx], dist[nx][ny]);
				}
			}
		}
			
	}
	
	cout<<dist[s[n-1]][t[n-1]];
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...