好难的一道题。

题意:一个机器人要逃出监狱,每走一步消耗一点电量,初始时电量是满的。给一个n*m(n,m<=15)的字符数组代表监狱,F代表起始点,G代表补充满电量,每个G只能补充一次,Y代表开关,D不能经过,S表示空地。要求打开所有开关,也就是经过所有Y点,电池的满电量最少是多少。如果不能逃出输出-1。G和Y的个数和不会超过15。

题解:二分答案。通过bfs预处理出G,Y,F两两之间的距离,然后转化成TSP求解。借鉴了别人的代码。

#include <bits/stdc++.h>
#define clr(x,c) memset(x,c,sizeof(x))
using namespace std; struct Point {
int x, y;
int d;
Point(int x, int y, int d) : x(x), y(y), d(d) {}
Point(int x, int y) : x(x), y(y), d(0) {}
Point() {} bool operator ==(const Point a) const {
if (x == a.x && y == a.y) return true;
return false;
} } p[50]; int m, n;
char mp[20][20];
int cf;
int dis[20][20];
int cnt = 0;
int ac = 0; // 所有y的集合
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int vis[20][20];
int dp[1<<17][20]; bool ok(int x, int y)
{
if (x < n && x >= 0 && y < m && y >= 0 &&
mp[x][y] != 'D' && !vis[x][y])
return true;
return false;
} int bfs(int a, int b)
{
clr(vis, 0);
queue<Point> q;
q.push(p[a]);
vis[p[a].x][p[a].y] = 1;
while (!q.empty()) {
Point now = q.front();
q.pop(); if (now == p[b]) return now.d;
for (int i = 0; i < 4; ++i) {
int nx = now.x + dir[i][0];
int ny = now.y + dir[i][1];
if (!ok(nx, ny)) continue;
int nd = now.d + 1;
q.push(Point(nx, ny, nd));
vis[nx][ny] = 1;
}
}
return -1;
} void getDis()
{
for (int i = 0; i < cnt; ++i) {
for (int j = i; j < cnt; ++j) {
if (i == j) dis[i][j] = 0;
else dis[j][i] = dis[i][j] = bfs(i, j);
}
}
} bool canGo(int en)
{
clr(dp, -1);
int st = (1 << cnt);
dp[1 << cf][cf] = en;
for (int i = 0; i < st; ++i) {
for (int j = 0; j < cnt; ++j) {
if ( !((1 << j) & i) || dp[i][j] == -1 ) continue;
if ((i & ac) == ac) return true;
for (int k = 0; k < cnt; ++k) {
if ( (1 << k) & i || dis[j][k] == -1 || dp[i][j] < dis[j][k] ) continue;
int nt = (1 << k) | i;
dp[nt][k] = max(dp[nt][k], dp[i][j] - dis[j][k]);
if (mp[ p[k].x ][ p[k].y ] == 'G') dp[nt][k] = en;
}
}
}
return false;
} int main()
{
while (~scanf("%d%d", &n, &m)) {
if (n == 0 && m == 0) break; for (int i = 0; i < n; ++i)
scanf("%s", mp[i]); ac = cnt = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (mp[i][j] == 'F') {
cf = cnt;
ac += (1 << cnt);
p[cnt++] = Point(i, j);
} else if (mp[i][j] == 'G') {
p[cnt++] = Point(i, j);
} else if (mp[i][j] == 'Y') {
ac += (1 << cnt);
p[cnt++] = Point(i, j);
}
}
} getDis(); int l = 0, r = 300;
while (l <= r) {
int mid = (l + r) >> 1;
if (canGo(mid)) r = mid - 1;
else l = mid + 1;
}
if (l >= 300) l = -1;
printf("%d\n", l);
}
return 0;
}

  

hdu3681--Prison Break(TSP+二分)的更多相关文章

  1. HDU3681 Prison Break

    Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  2. HDU 3681 Prison Break(BFS+二分+状态压缩DP)

    Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...

  3. hdu 3681 Prison Break (TSP问题)

    Prison Break Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  4. Prison Break

    Prison Break 时间限制: 1 Sec  内存限制: 128 MB提交: 105  解决: 16[提交][状态][讨论版] 题目描述 Scofild又要策划一次越狱行动,和上次一样,他已经掌 ...

  5. hdu 3681 Prison Break(状态压缩+bfs)

    Problem Description Rompire . Now it’s time to escape, but Micheal# needs an optimal plan and he con ...

  6. hdu3511 Prison Break 圆的扫描线

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3511 题目: Prison Break Time Limit: 10000/5000 MS ( ...

  7. 1254 - Prison Break

    1254 - Prison Break   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Mic ...

  8. HDU 3681 Prison Break (二分 + bfs + TSP)

    题意:给定上一个 n * m的矩阵,你的出发点是 F,你初始有一个电量,每走一步就会少1,如果遇到G,那么就会加满,每个G只能第一次使用,问你把所有的Y都经过,初始电量最少是多少. 析:首先先预处理每 ...

  9. HDU 3681 Prison Break(状态压缩dp + BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...

随机推荐

  1. ArcGIS API for JavaScript 学习笔记(一)

    终于开始了 噩梦一般的ArcGIS 我特别不习惯这种结构化的程序写法 写起来特别吃力 特别是把几个功能整合到同一个页面去的时候. 写程序的时候,一般我喜欢先写个Demo然后再把Demo上面的功能加到页 ...

  2. AppExtention - today

    声明: 本文转自王巍 WWDC 2014 Session笔记 - iOS 通知中心扩展制作入门 本文是我的 WWDC 2014 笔记 中的一篇,涉及的 Session 有 Creating Exten ...

  3. iOS多线程常用类说明--备用参考

    iOS的多线程,涉及到如下一些类,这里集中做个介绍,免得混淆. 1.NSTimer 很显然,这是定时器类 2.NSTask iOS 不支持 NSTask 在很多并发操作的时候,多线程太耗资源,也太危险 ...

  4. poj 2440 (找递推公式)

    http://poj.org/problem?id=2440 DNA Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3254 ...

  5. BZOJ 1733: [Usaco2005 feb]Secret Milking Machine 神秘的挤奶机

    Description 约翰正在制造一台新型的挤奶机,但他不希望别人知道.他希望尽可能久地隐藏这个秘密.他把挤奶机藏在他的农场里,使它不被发现.在挤奶机制造的过程中,他需要去挤奶机所在的地方T(1≤T ...

  6. Searching for Approximate Nearest Neighbours

    Searching for Approximate Nearest Neighbours Nearest neighbour search is a common task: given a quer ...

  7. jquery dom ready, jqery2.1.1实现-源码分析

    本文链接http://www.cnblogs.com/Bond/p/4178311.html jquery document  ready的实现其很很简,虽说简单,其很很多人还是没去关注过它的实现.我 ...

  8. 解决Ubuntu root账户的问题

    问题的提出:在Linux环境下,许多操作需要有管理员权限才能进行.如果没有root权限,就连基本的文件拷贝操作都只能在用户文件夹下进行,而对于Ubuntu系统,安装时是没有设定root帐号的,那么怎样 ...

  9. 【 NOIP2015 DAY1 T2 信息传递】带权并查集

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  10. delphi中的各种文件类型介绍

    1.DPR: Delphi Project文件,包含了Pascal代码.应用系统的工程文件2.PAS: Pascal文件,Pascal单元的源代码,可以是与窗体有关的单元或是独立的单元.3.DFM:D ...