一来想用普通BFS实现,无奈超时,怒换思路
遍历所有的点且仅一次,可转化为TSP问题变形
求满足的最小值,显然二分之
遍历所有的点且仅一次,可转化为TSP问题变形
求满足的最小值,显然二分之
推荐一个TSP好的博客,一看就懂 点击打开链接
类似题目: Disney's FastPass hdu4114 hdu4085 Peach Blossom Spring
Accepted | 3681 | 296MS | 2372K |
//#pragma comment(linker, "/STACK:102400000,102400000")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//STL
#define PB push_back
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-10;
const int maxn = 16;
const LL MOD = 1e9 + 7;
const int F = 1, G = 2, Y = 3;
int n, m, cnt, sta, all;
struct SWITCH{
short int x, y, kind;
}sw[maxn];
struct node{
short int x, y, step;
node(int a, int b, int s) : x(a), y(b), step(s) {}
};
char mat[maxn][maxn];
int dis[maxn][maxn], dp[maxn][1 << 15], id[maxn][maxn];
bool vis[maxn][maxn];
int dir[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
void bfs(int th)
{
CLR(vis, 0);
queue<node> Q;
vis[sw[th].x][sw[th].y] = 1;
dis[th][th] = 0;
Q.push(node(sw[th].x, sw[th].y, 0));
while (!Q.empty())
{
node t = Q.front(); Q.pop();
REP(i, 4)
{
int x = t.x + dir[i][0], y = t.y + dir[i][1];
if (x < 0 || x >= n || y < 0 || y >= m || mat[x][y] == 'D') continue;
if (!vis[x][y])
{
if (id[x][y] != -1)
dis[th][id[x][y]] = t.step + 1;
vis[x][y] = 1;
Q.push(node(x, y, t.step + 1));
}
}
}
}
bool ok(int full, int goal)
{
CLR(dp, -1);
dp[sta][1 << sta] = full;
REP(s0, all)
{
REP(i, cnt)
{
if (dp[i][s0] == -1) continue;
if ((s0 & goal) == goal) return 1;
REP(j, cnt)
{
if (s0 & (1 << j)) continue;
int ns = s0 | (1 << j);
dp[j][ns] = max(dp[j][ns], dp[i][s0] - dis[i][j]);
if (dp[j][ns] >= 0 && sw[j].kind == G)
dp[j][ns] = full;
}
}
}
return false;
}
void solve()
{
CLR(dis, 0x3f);
int goal = 0;
all = (1 << cnt);
REP(i, cnt)
bfs(i);
REP(i, cnt)
if (sw[i].kind != G)
goal |= (1 << i);
int L = 0, R = n * m * 2;
while (L <= R)
{
int mid = (L + R) >> 1;
if (ok(mid, goal))
R = mid - 1;
else
L = mid + 1;
}
if (L > n * m * 2)
WI(-1);
else
WI(L);
}
int main()
{
while (~RII(n, m), n || m)
{
cnt = 0;
CLR(id, -1);
REP(i, n)
{
RS(mat[i]);
REP(j, m)
{
if (mat[i][j] == 'F')
id[i][j] = cnt, sta = cnt, sw[cnt].kind = F, sw[cnt].x = i, sw[cnt].y = j, ++cnt;
else if (mat[i][j] == 'G')
id[i][j] = cnt, sw[cnt].kind = G, sw[cnt].x = i, sw[cnt].y = j, ++cnt;
else if (mat[i][j] == 'Y')
id[i][j] = cnt, sw[cnt].kind = Y, sw[cnt].x = i, sw[cnt].y = j, ++cnt;
}
}
solve();
}
}
DFS版本,只对有用节点进行DFS即可
31ms
//#pragma comment(linker, "/STACK:102400000,102400000")
//HEAD
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define CPY(a, b) memcpy(a, b, sizeof(a))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//STL
#define SZ(V) (int)V.size()
#define PB push_back
#define EQ(a, b) (fabs((a) - (b)) <= 1e-10)
#define ALL(c) (c).begin(), (c).end()
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(s) printf("%s\n", s)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 0x3f3f3f3f;
const double eps = 1e-10;
const int maxn = 16;
const LL MOD = 1e9 + 7;
const int F = 1, G = 2, Y = 3;
int n, m, cnt, sta, all, goal;
struct SWITCH{
short int x, y, kind;
}sw[maxn];
struct node{
short int x, y, step;
node(int a, int b, int s) : x(a), y(b), step(s) {}
};
char mat[maxn][maxn];
int dis[maxn][maxn], dp[maxn][1 << 15], id[maxn][maxn];
bool vis[maxn][maxn];
int dir[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
void bfs(int th)
{
CLR(vis, 0);
queue<node> Q;
vis[sw[th].x][sw[th].y] = 1;
dis[th][th] = 0;
Q.push(node(sw[th].x, sw[th].y, 0));
while (!Q.empty())
{
node t = Q.front(); Q.pop();
REP(i, 4)
{
int x = t.x + dir[i][0], y = t.y + dir[i][1];
if (x < 0 || x >= n || y < 0 || y >= m || mat[x][y] == 'D') continue;
if (!vis[x][y])
{
if (id[x][y] != -1)
dis[th][id[x][y]] = t.step + 1;
vis[x][y] = 1;
Q.push(node(x, y, t.step + 1));
}
}
}
}
bool dfs(int u, int s0, int left, int full)
{
if ((s0 & goal) == goal) return 1;
REP(v, cnt)
if (left >= dis[u][v])
{
if (s0 & (1 << v)) continue;
if (sw[v].kind == G)
{
if (dfs(v, s0 | (1 << v), full, full))
return 1;
}
else
{
if (dfs(v, s0 | (1 << v), left - dis[u][v], full))
return 1;
}
}
return 0;
}
bool ok(int mid)
{
return dfs(sta, (1 << sta), mid, mid);
}
void solve()
{
CLR(dis, 0x3f);
goal = 0;
all = (1 << cnt);
REP(i, cnt)
bfs(i);
REP(i, cnt)
if (sw[i].kind == Y && dis[sta][i] == INF)
{
WI(-1);
return;
}
REP(i, cnt)
if (sw[i].kind != G)
goal |= (1 << i);
int L = 0, R = n * m * 2;
while (L <= R)
{
int mid = (L + R) >> 1;
if (ok(mid))
R = mid - 1;
else
L = mid + 1;
}
if (L > n * m * 2)
WI(-1);
else
WI(L);
}
int main()
{
while (~RII(n, m), n || m)
{
cnt = 0;
CLR(id, -1);
REP(i, n)
{
RS(mat[i]);
REP(j, m)
{
if (mat[i][j] == 'F')
id[i][j] = cnt, sta = cnt, sw[cnt].kind = F, sw[cnt].x = i, sw[cnt].y = j, ++cnt;
else if (mat[i][j] == 'G')
id[i][j] = cnt, sw[cnt].kind = G, sw[cnt].x = i, sw[cnt].y = j, ++cnt;
else if (mat[i][j] == 'Y')
id[i][j] = cnt, sw[cnt].kind = Y, sw[cnt].x = i, sw[cnt].y = j, ++cnt;
}
}
solve();
}
}