Problem:
Problem E: Light

Problem

$W \times H$ の二次元のマス上に$N$個の街灯がある。

がっちょ君は$(1,1)$からスタートして$(W,H)$に行きたい。

がっちょ君は暗いところが怖いので、街灯により明るくなっているマスしか歩きたくない。

最初、すべての街灯はその街灯のあるマスのみを明るくしている。

そこで、がっちょ君は好きな街灯$i$に対してコスト$r_i$を設定することにした。なお、コストを設定しない街灯があってもよい。

街灯$i$はコスト$r_i$を消費することにより、その街灯を中心にマンハッタン距離で$r_i$以内の範囲を明るくすることができる。ただしコストは正の整数とする。

がっちょ君は上下左右のいずれかの方向に隣接するマスに移動する事ができる。

がっちょ君は$r_i$の合計値を最小になるように設定することにした。そのときの合計値を求めよ。

2つの地点 $(a,b)$ と $(c,d)$ 間のマンハッタン距離は $|a−c|$+$|b−d|$ で表される。

Input

入力は以下の形式で与えられる。

$W$ $H$ $N$
$x_1$ $y_1$
...
$x_N$ $y_N$

入力はすべて整数で与えられる。

1行目に$W$と$H$と$N$が空白区切りで与えられる。

続く$N$行に街灯$i$の座標$($$x_i$,$y_i$$)$が空白区切りで与えられる。

Constraints

入力は以下の条件を満たす。

$1 \leq W \leq 500$

$1 \leq H \leq 500$

$1 \leq N \leq 100$

$1 \leq N \leq W \times H$

$1 \leq $$x_i$$ \leq W$

$1 \leq $$y_i$$ \leq H$

同じ座標に複数の街灯はない

Output

$r_i$の合計値の最小値を1行に出力せよ。

Sample Input 1

10 10 1
6 6

Sample Output 1

10

Sample Input 2

5 10 3
3 9
2 8
5 1

Sample Output 2

8

Sample Input 3

1 1 1
1 1

Sample Output 3

0

Solution in C (judge verdict: Accepted)

// AOJ 3030 Light
// 2018.4.14 bal4u
 
#include <stdio.h>
//#include <stdlib.h>
#include <string.h>
 
#define QMAX 100000
typedef struct { int t, s, c; } QUE;
QUE que[QMAX]; int qsize;

#define PARENT(i) ((i)>>1)
#define LEFT(i)   ((i)<<1)
#define RIGHT(i)  (((i)<<1)+1)

void min_heapify(int i)
{
	int l, r, min;
	QUE qt;

	l = LEFT(i), r = RIGHT(i);
	if (l < qsize && que[l].t < que[i].t) min = l; else min = i;
	if (r < qsize && que[r].t < que[min].t) min = r;
	if (min != i) {
		qt = que[i], que[i] = que[min], que[min] = qt;
		min_heapify(min);
	}
}

void deq()
{
	que[0] = que[--qsize];
	min_heapify(0);
}

void enq(int s, int t, int c)
{
	int i, min;
	QUE qt;

	i = qsize++;
	que[i].s = s, que[i].t = t, que[i].c = c;
	while (i > 0 && que[min = PARENT(i)].t > que[i].t) {
		qt = que[i], que[i] = que[min], que[min] = qt;
		i = min;
	}
}

//#define getchar_unlocked()  getchar()
int in()
{
	int n = 0, c = getchar_unlocked();
	do n = 10*n + (c & 0xf), c = getchar_unlocked(); while (c >= '0');
	return n;
}

#define INF 0x10101010
#define ABS(a)   ((a)>=0?(a):-(a))
int x[102], y[102];
int dist[102][1002];

int dijkstra(int n)
{
	int s, e, t, nt, c;

	memset(dist, INF, sizeof(dist));
	qsize = 0;
	for (s = 0; s < n; s++) c = x[s]+y[s], enq(s, c, c), dist[s][c] = c;
	while (qsize) {
		s = que[0].s, t = que[0].t, c = que[0].c, deq();
//printf("s %d, t %d, c %d, N %d, qsize %d\n", s, t, c, n, qsize);
		if (s == n) break; 
		if (dist[s][c] < t) continue;
		for (e = 0; e < n; e++) if (e != s) {
			nt = ABS(x[e]-x[s])+ABS(y[e]-y[s])-c-1;
			if (nt < 0) nt = 0;
			if (dist[e][nt] > t+nt) dist[e][nt] = t+nt, enq(e, t+nt, nt);
		}
		nt = ABS(x[n]-x[s])+ABS(y[n]-y[s])-c;
		if (nt < 0) nt = 0;
		if (dist[n][nt] > t+nt) dist[n][nt] = t+nt, enq(n, t+nt, nt);
	}
	return t;
}

int main()
{
	int W, H, N, i;

	W = in(), H = in(), N = in();
	for (i = 0; i < N; i++) x[i] = in()-1, y[i] = in()-1;
	x[N] = W-1, y[N] = H-1;
	printf("%d\n", dijkstra(N));
	return 0;
}