【最短路】SSL_1319 埃雷萨拉斯寻宝

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SSL_hzb/article/details/89601103

题意

给出一个矩阵,求出从第一行走到最后一行的最少花费。其中每种格子第一次走到都要花费相应的代价,同种格子之间可以直接传送到达。

思路

按照题意的要求建边,然后建立一个超级源点连到第一行,超级汇点连到最后一行,跑最短路就可以求出答案了。

代码

#include<queue>
#include<cstdio>
#include<cstring>

int n, p, h, tot;
int a[2501], map[51][51], lian[2501][2501], head[2503], next[6250001], ver[6250001], edge[6250001], d[2503];

void add(int u, int v, int w) {
	ver[++tot] = v;
	next[tot] = head[u];
	edge[tot] = w;
	head[u] = tot;
}

int change(int x, int y) {
	return (x - 1) * n + y;
}

void spfa() {
	std::queue<int> q;
	int v[2503];
	memset(v, 0, sizeof(v));
	memset(d, 127 / 3, sizeof(d));
	q.push(0);
	v[0] = 1;
	d[0] = 0;
	while (q.size()) {
		int u = q.front();
		q.pop();
		v[u] = 0;
		for (int i = head[u]; i; i = next[i]) {
			int to = ver[i];
			if (d[to] > d[u] + edge[i]) {
				d[to] = d[u] + edge[i];
				if (!v[to]) {
					v[to] = 1;
					q.push(to);
				}
			}
		}
	}
}

int main() {
	scanf("%d %d %d", &n, &p, &h);
	for (int i = 1; i <= p; i++)
		scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			scanf("%d", &map[i][j]);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {			
			for (int k = 1; k <= n; k++)
				for (int l = 1; l <= n; l++)
					if (i != k && j != l && map[i][j] == map[k][l] && !lian[change(i, j)][change(k, l)])
						add(change(i, j), change(k, l), 0), lian[change(i, j)][change(k, l)] = 1;
			int u = change(i, j);
			if (i > 1) {
				int v = change(i - 1, j); 
				if (!lian[u][v]) add(u, v, a[map[i - 1][j]]), lian[u][v] = 1;
			}
			if (i < n) {
				int v = change(i + 1, j);
				if (!lian[u][v]) add(u, v, a[map[i + 1][j]]), lian[u][v] = 1;
			}
			if (j > 1) {
				int v = change(i, j - 1);
				if (!lian[u][v]) add(u, v, a[map[i][j - 1]]), lian[u][v] = 1;
			}
			if (j < n) {
				int v = change(i, j + 1);
				if (!lian[u][v]) add(u, v, a[map[i][j + 1]]), lian[u][v] = 1;
			}

		}
	for (int i = 1; i <= n; i++) {
		add(0, i, a[map[1][i]]);
		add(n * n - i + 1, n * n + 1, 0);
	}
	spfa();
	if (d[n * n + 1] >= h) printf("NO");
	else printf("%d", h - d[n * n + 1]);
}

猜你喜欢

转载自blog.csdn.net/SSL_hzb/article/details/89601103