// hdu 3681 Prison Break bfs + 二分 + TSP
//
// 解题思路:
//
// 因为G,Y不超过15,这样讲这些点单独记录下来,bfs求出
// 两两之间的距离.二分用判断TSP判断.所转化的问题就是在
// F和Y的集合中,找到TSP路径的最小值即可.
//
// 感悟:
//
// 觉得这题,十分巧妙,仔细想来确实不是很难,但是不好
// 想,总的来说还是自己的水平不足吧,继续加油!!!FIGHTING!
// !!
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#define For(x,a,b,c) for (int x = a; x <= b; x += c)
#define Ffor(x,a,b,c) for (int x = a; x >= b; x -= c)
#define cls(x,a) memset(x,a,sizeof(x))
using namespace std;
typedef long long ll;
const int MAX_N = 108;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const int dx[4] = {-1,0,1,0};
const int dy[4] = {0,1,0,-1};
int N;
int M;
char mp[20][20];
int dist[20][20];
int dp[1<<17][17];
struct Point{
int x;
int y;
Point(){
}
Point(int x,int y):x(x),y(y){
}
}p[20];
int cnt = 0;
int state;
int start;
void input(){
cnt = 0;
state = 0;
start = 0;
For(i,1,N,1){
scanf("%s",mp[i]+1);
For(j,1,M,1){
if (mp[i][j] == 'F'){
start = cnt;
state |= 1 << cnt;
p[cnt].x = i;
p[cnt++].y = j;
}else if (mp[i][j] == 'G'){
p[cnt].x = i;
p[cnt++].y = j;
}else if (mp[i][j] == 'Y'){
p[cnt].x = i;
p[cnt].y = j;
state |= 1 << cnt;
cnt++;
}
}
}
}
int bfs(int s,int t){
Point st = p[s];
Point ed = p[t];
int ti[20][20];
cls(ti,-1);
queue<Point> que;
que.push(st);
ti[st.x][st.y] = 0;
while(!que.empty()){
Point u = que.front();
que.pop();
if (u.x == ed.x && u.y == ed.y){
return ti[u.x][u.y];
}
For(i,0,3,1){
int tx = u.x + dx[i];
int ty = u.y + dy[i];
if (tx < 1 || tx > N || ty < 1 || ty > M)
continue;
if (mp[tx][ty] == 'D')
continue;
if (ti[tx][ty] != -1)
continue;
ti[tx][ty] = ti[u.x][u.y] + 1;
que.push(Point(tx,ty));
}
}
return INF;
}
void getdist(){
For(i,0,cnt-1,1){
For(j,0,cnt-1,1){
dist[i][j] = bfs(i,j);
}
}
}
void print(){
For(i,0,cnt-1,1){
For(j,0,cnt-1,1){
printf("%d ",dist[i][j]);
}
puts("");
}
}
bool ok(int x){
cls(dp,-1);
dp[1<<start][start] = x;
For(i,0,(1<<cnt)-1,1){
For(u,0,cnt-1,1){
if (dp[i][u] == -1)
continue;
if (i & (1 << u) == 0)
continue;
if ((i & (state)) == state)
if (dp[i][u]!=-1)
return true;
For(v,0,cnt-1,1){
if (u == v)
continue;
if (dist[u][v] == INF)
continue;
if (i & (1<< v))
continue;
int tmp = dp[i][u] - dist[u][v];
if (tmp < 0)
continue;
dp[i | (1<< v)][v] = max(dp[i | (1<< v)][v],tmp);
if (mp[p[v].x][p[v].y] == 'G')
dp[i | (1 << v)][v] = x;
}
}
}
return false;
}
void solve(){
getdist();
int L = 1,R = 400;
int flag = 0;
while(L+1<=R){
int MID = (L + R) >> 1;
if (ok(MID)){
flag = 1;
R = MID;
}else {
L = MID + 1;
}
}
if (!flag)
puts("-1");
else
printf("%d\n",L);
//print();
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
while(scanf("%d%d",&N,&M)!=EOF){
if (N == 0 && M == 0)
break;
input();
solve();
}
return 0;
}
hdu 3681 Prison Break bfs + 二分 + TSP
最新推荐文章于 2022-04-10 01:42:22 发布
本文介绍了一道经典的算法竞赛题目“Prison Break”的解决方案,该题结合了宽度优先搜索(BFS)、二分查找及旅行商问题(TSP)等算法思想。文章详细解释了解题思路,即通过BFS预处理特定点之间的距离,并使用二分法辅助解决TSP问题,最终找到最优路径。
摘要由CSDN通过智能技术生成