题意:求回收所有垃圾的最短路
思路:先BFS处理两个垃圾的距离,然后DFS记忆化搜索
dp[i][state]表示处理到第i个后状态是state的最短路
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; const int MAXN = 30; const int INF = 0x3f3f3f3f; struct Point { int x,y; }point[20]; struct node { int x,y,step,f; node(int _x, int _y, int _step, int _f) { x = _x, y = _y, step = _step, f = _f; } bool operator< (const node a)const { return f > a.f; } }; char map[MAXN][MAXN]; int n,m; int dx[4] = {1,-1,0,0}; int dy[4] = {0,0,1,-1}; int dis[MAXN][MAXN], vis[MAXN][MAXN]; int dp[12][1<<12],sum; int check(int x, int y) { if (x > 0 && x <= n && y > 0 && y <= m && map[x][y] != 'x') return 1; return 0; } int getdiff(const Point &a, const Point &b) { return abs(a.x-b.x) + abs(a.y-b.y); } int bfs(const Point &a, const Point &b) { priority_queue<node > q; q.push(node(a.x, a.y, 0, getdiff(a, b))); memset(vis, 0, sizeof(vis)); vis[a.x][a.y] = 1; while (!q.empty()) { node cur = q.top(); q.pop(); if (cur.x == b.x && cur.y == b.y) return cur.step; for (int i = 0; i < 4; i++) { Point tmp; tmp.x = cur.x + dx[i]; tmp.y = cur.y + dy[i]; if (check(tmp.x, tmp.y) && !vis[tmp.x][tmp.y]) { vis[tmp.x][tmp.y] = 1; int f = cur.step+1+getdiff(tmp, b); q.push(node(tmp.x, tmp.y, cur.step+1, f)); } } } return -1; } int getFlag(int i) { return 1<<i; } int dfs(int st, int u) { if (dp[u][st] != INF) return dp[u][st]; int s = st^getFlag(u-1); if (s == 0) return dis[0][u]; for (int i = 1; i <= sum; i++) if (s & getFlag(i-1)) dp[u][st] = min(dp[u][st], dfs(s, i)+dis[i][u]); return dp[u][st]; } int main() { while (scanf("%d%d", &m, &n) != EOF && n+m) { memset(map, 0, sizeof(map)); sum = 0; for (int i = 1; i <= n; i++) { scanf("%s", &map[i][1]); for (int j = 1; j <= m; j++) if (map[i][j] == '*') { ++sum; point[sum].x = i; point[sum].y = j; } else if (map[i][j] == 'o') { point[0].x = i; point[0].y = j; } } int flag = 0; for (int i = 0; i <= sum; i++) { for (int j = i; j <= sum; j++) { if (i == j) dis[i][j] = 0; else { dis[i][j] = dis[j][i] = bfs(point[i], point[j]); if (dis[i][j] == -1) { flag = 1; break; } } } } if (flag) { printf("-1\n"); continue; } int ends = getFlag(sum) - 1; for (int i = 0; i <= sum; i++) for (int j = 0; j <= ends; j++) dp[i][j] = INF; dp[0][0] = 0; int ans = INF; for (int i = 1; i <= sum; i++) ans = min(ans, dfs(ends, i)); printf("%d\n", ans); } return 0; }
POJ - 2688 Cleaning Robot,布布扣,bubuko.com
时间: 2024-10-05 18:19:31