[UVA 10605]钻石矿道【启发式搜索+状态压缩】
2019-08-06 09:32
176 查看
[UVA 10605]钻石矿道
很好的一道题就是了,做了两遍了,要理清楚其中的状态转移,其余的倒是不难处理,这里的dp[ i ][ j ]表示的是我们这个一块,也就是它们被合并成一个块的包含j这个点的最短路径。g[ i ]表示的是状态i下的这个块的出去的最短距离。f[ i ]表示的是这个状态下出去的最短距离,没必要在一个块中。
[code]#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r #define MP(x, y) make_pair(x, y) using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 15; const int dir[4][2] = { -1, 0, 0, -1, 0, 1, 1, 0 }; int N, M, tot, h[maxN], g[1<<maxN], f[1<<maxN]; char mp[maxN][maxN]; struct node { int x, y; node(int a=0, int b=0):x(a), y(b) {} }a[maxN * maxN]; inline int _dis(node e1, node e2) { return abs(e1.x - e2.x) + abs(e1.y - e2.y); } bool vis[maxN][maxN]; pair<node, int> now; queue<pair<node, int>> Q; inline int bfs(int sx, int sy) { memset(vis, false, sizeof(vis)); while(!Q.empty()) Q.pop(); Q.push(MP(node(sx, sy), 0)); vis[sx][sy] = true; while(!Q.empty()) { now = Q.front(); Q.pop(); for(int i=0, xx, yy; i<4; i++) { xx = now.first.x + dir[i][0]; yy = now.first.y + dir[i][1]; if(vis[xx][yy]) continue; vis[xx][yy] = true; if(mp[xx][yy] == '#') return now.second + 1; Q.push(MP(node(xx, yy), now.second + 1)); } } return 0; } int dis[maxN], dp[1<<maxN][maxN]; inline void pre_did() { for(int i=0; i<tot; i++) dis[i] = bfs(a[i].x, a[i].y); for(int i=0; i<tot; i++) dp[1<<i][i] = dis[i]; for(int i=1; i<(1<<tot); i++) { for(int j=0; j<tot; j++) { if((1<<j) & i) { for(int k=0; k<tot; k++) { if(((1<<k) & i) && k != j) //不能是两个相同的点 { dp[i][j] = min(dp[i][j], dp[i^(1<<j)][k] + _dis(a[j], a[k])); } } } } for(int j=0; j<tot; j++) g[i] = min(g[i], dp[i][j]); } for(int i=1; i<(1<<tot); i++) { for(int j=1; j<=i; j++) { if((i & j) == j) { f[i] = min(f[i], f[i^j] + g[j]); } } } printf("%d\n", f[(1<<tot) - 1]); } inline void init() { tot = 0; memset(dp, INF, sizeof(dp)); dp[0][0] = 0; memset(g, INF, sizeof(g)); memset(f, INF, sizeof(f)); g[0] = f[0] = 0; } int main() { // freopen("uva10605.in", "r", stdin); // freopen("uva10605.out", "w", stdout); int T; scanf("%d", &T); while(T--) { scanf("%d%d", &N, &M); init(); for(int i=1; i<=N; i++) { scanf("%s", mp[i] + 1); for(int j=1; j<=M; j++) if(mp[i][j] == '*') a[tot++] = node(i, j); } pre_did(); } return 0; }
相关文章推荐
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
- Uva 11825 - Hackers' Crackdown 状态压缩
- UVa11806 - Cheerleaders(容斥原理+状态压缩)
- uva10944 状态压缩bfs or DP
- UVA 1533 - Moving Pegs 状态压缩 + bfs
- uva11825(状态压缩+枚举子集)黑客的攻击
- 黑客的攻击 Hacker‘s crackdown UVA11825 状态压缩动态规划
- uvalive 2965(状态压缩)
- uva 10817 状态压缩DP
- UVALive 6625_状态压缩
- uva 818 Cutting Chains(dfs+状态压缩)
- Uva 11825 - Hackers’ Crackdown 状态压缩DP
- uva_10604 - Chemical Reaction( Hash+状态压缩 )
- UVA-10911 - Forming Quiz Teams(状态压缩)
- UVA 1252 Twenty Questions 状态压缩dp 记忆化搜索
- UVa 10817 - Headmaster's Headache (简单DP 状态压缩)
- Uva 11825 - Hackers' Crackdown 状态压缩
- UVa:10911 Forming Quiz Teams(状态压缩)
- hash+状态压缩+uva10944
- UVA 1508 - Equipment 状态压缩 枚举子集 dfs