HDU4568 Hunter
题意:\(n*m\)的矩形,每个格子有权值,并给出若干个在矩阵中的点的位置,要求从矩阵外任意位置进入矩阵到达所有给定的点并出去,求路径上最小权值和
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 210;
const int inf = 0x3f3f3f3f;
struct node
{
int x, y;
node(int _x = 0, int _y = 0) : x(_x), y(_y) {}
} s[15];
struct qnode
{
int x, y;
int c;
qnode(int _x = 0, int _y = 0, int _c = 0) : x(_x), y(_y), c(_c) {}
bool operator<(const qnode &r) const
{
return c > r.c;
}
};
int a[maxn][maxn], n, m;
int dis[15][15];
int dist[maxn][maxn], vis[maxn][maxn];
int out[15];
int dp[1 << 15][15];
int dir[4][2] = {
1, 0,
0, 1,
-1, 0,
0, -1
};
bool limit(int x, int y)
{
return x >= 0 && x < n && y >= 0 && y < m && a[x][y] != -1;
}
void dij(node st, int id)
{
memset(dist, 0x3f, sizeof(dist));
priority_queue<qnode> que;
dist[st.x][st.y] = 0;
que.push(qnode(st.x, st.y, 0));
qnode tmp;
while (!que.empty())
{
tmp = que.top();
que.pop();
node u = node(tmp.x, tmp.y);
if (vis[u.x][u.y] == id)
continue;
vis[u.x][u.y] = id;
for (int i = 0; i < 4; i++)
{
node now = node(u.x + dir[i][0], u.y + dir[i][1]);
if (limit(now.x, now.y))
{
int cost = a[now.x][now.y];
if (vis[now.x][now.y] != id && dist[now.x][now.y] > dist[u.x][u.y] + cost)
{
dist[now.x][now.y] = dist[u.x][u.y] + cost;
que.push(qnode(now.x, now.y, dist[now.x][now.y]));
}
}
}
}
}
int main()
{
int t, k;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
scanf("%d", &k);
for (int i = 0; i < k; i++)
scanf("%d%d", &s[i].x, &s[i].y);
memset(out, inf, sizeof(out));
memset(vis, 0, sizeof(vis));
memset(dp, inf, sizeof(dp));
for (int i = 0; i < k; i++)
{
dij(s[i], i + 1);
for (int j = 0; j < k; j++)
dis[i][j] = dist[s[j].x][s[j].y]; //i到j的最短距离,不包括i点权值
for (int j = 0; j < n; j++)
{
if (out[i] > dist[j][0])
out[i] = dist[j][0];
if (out[i] > dist[j][m - 1])
out[i] = dist[j][m - 1];
}
for (int j = 0; j < m; j++)
{
if (out[i] > dist[0][j])
out[i] = dist[0][j];
if (out[i] > dist[n - 1][j])
out[i] = dist[n - 1][j];
}
dp[1 << i][i] = out[i] + a[s[i].x][s[i].y]; //边界到该点的最短距离,加上该点权值
}
for (int i = 0; i < (1 << k); i++)
for (int j = 0; j < k; j++)
for (int _k = 0; _k < k; _k++)
if ((i & (1 << j)) == 0)
dp[i | (1 << j)][j] = min(dp[i | (1 << j)][j], dp[i][_k] + dis[_k][j]);
int val = inf;
for (int i = 0; i < k; i++)
if (val > dp[(1 << k) - 1][i] + out[i])
val = dp[(1 << k) - 1][i] + out[i];
if (val == inf)
puts("0");
else
printf("%d\n", val);
}
return 0;
}

浙公网安备 33010602011771号