2013 杭州 onsite B题
bfs预处理后,dfs枚举或tsp
bfs预处理后,dfs枚举:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include <queue>
#define REP(i, n) for(int i=0; i<n; i++)
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define LL long long
#define PB push_back
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
int n, m;
int k;
int di[] = {0, 1, 0, -1};
int dj[] = {1, 0, -1, 0};
char mat[110][110];
int dis[5][110][110];
int g[6][2];
int op[6];
int vis[6];
int ans;
void dfs(int step, int now)
{
if (step > k)
{
ans = min(ans, now);
return ;
}
int fr = op[step - 1];
for (int r = 1; r <= k; r++)
{
if (!vis[r])
{
vis[r] = 1;
op[step] = r;
int to = r;
dfs(step + 1, now + dis[fr][g[to][0]][g[to][1]]);
vis[r] = 0;
}
}
}
bool check(int i, int j)
{
if (i >= 0 && i < n && j >= 0 && j < m) return 1;
return 0;
}
bool bfs(int step)
{
CLR(dis[step], INF);
int si = g[step][0];
int sj = g[step][1];
dis[step][si][sj] = 0;
queue<int>q;
while (!q.empty()) q.pop();
q.push(si * 1000 + sj);
int num = 0;
while (!q.empty())
{
int u = q.front(); q.pop();
int ui = u / 1000;
int uj = u % 1000;
if (mat[ui][uj] <= '9' && mat[ui][uj] >= '0') num++;
if (num == k + 1) return 1;
REP(r, 4)
{
int vi = ui + di[r];
int vj = uj + dj[r];
if (check(vi, vj) && mat[vi][vj] != '#' && dis[step][vi][vj] > dis[step][ui][uj] + 1)
{
dis[step][vi][vj] = dis[step][ui][uj] + 1;
q.push(vi * 1000 + vj);
}
}
}
return 0;
}
int main()
{
int x, y;
while(scanf("%d%d", &n, &m), n+m)
{
REP(i, n)
{
scanf("%s", mat[i]);
REP(j, m)
{
if (mat[i][j] == '@')
{
g[0][0] = i;
g[0][1] = j;
mat[i][j] = '0';
}
}
}
scanf("%d", &k);
for (int i = 1; i <= k; i++)
{
scanf("%d%d", &x, &y);
x--;
y--;
g[i][0] = x;
g[i][1] = y;
mat[x][y] = '0' + i;
}
if (!bfs(0))
{
printf("-1\n");
}
else
{
FF(i, 1, k + 1) bfs(i);
ans = INF;
op[0] = 0;
CLR(vis, 0);
vis[0] = 1;
dfs(1, 0);
printf("%d\n", ans);
}
}
return 0;
}
bfs预处理后,tsp:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include <queue>
#define REP(i, n) for(int i=0; i<n; i++)
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define LL long long
#define PB push_back
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
int n, m;
int k;
int di[] = {0, 1, 0, -1};
int dj[] = {1, 0, -1, 0};
char mat[110][110];
int dis[5][110][110];
int g[6][2];
int ans;
int dp[5][1 << 5];
bool check(int i, int j)
{
if (i >= 0 && i < n && j >= 0 && j < m) return 1;
return 0;
}
bool bfs(int step)
{
CLR(dis[step], INF);
int si = g[step][0];
int sj = g[step][1];
dis[step][si][sj] = 0;
queue<int>q;
while (!q.empty()) q.pop();
q.push(si * 1000 + sj);
int num = 0;
while (!q.empty())
{
int u = q.front(); q.pop();
int ui = u / 1000;
int uj = u % 1000;
if (mat[ui][uj] <= '9' && mat[ui][uj] >= '0') num++;
if (num == k + 1) return 1;
REP(r, 4)
{
int vi = ui + di[r];
int vj = uj + dj[r];
if (check(vi, vj) && mat[vi][vj] != '#' && dis[step][vi][vj] > dis[step][ui][uj] + 1)
{
dis[step][vi][vj] = dis[step][ui][uj] + 1;
q.push(vi * 1000 + vj);
}
}
}
return 0;
}
int solve()
{
CLR(dp, INF);
dp[0][1] = 0;
int ALL = (1 << (k + 1)) - 1;
for (int ss = 0; ss <= ALL; ss++)
{
for (int i = 1; i <= k; i++)
{
for (int j = 0; j <= k; j++)
{
if (i != j && (ss & (1 << i)))
{
dp[i][ss] = min(dp[i][ss], dp[j][ss ^ (1 << i)] + dis[j][g[i][0]][g[i][1]]);
}
}
}
}
int ans = INF;
for (int i = 0; i <= k; i++)
ans = min(ans, dp[i][ALL]);
return ans;
}
int main()
{
int x, y;
while(scanf("%d%d", &n, &m), n+m)
{
REP(i, n)
{
scanf("%s", mat[i]);
REP(j, m)
{
if (mat[i][j] == '@')
{
g[0][0] = i;
g[0][1] = j;
mat[i][j] = '0';
}
}
}
scanf("%d", &k);
for (int i = 1; i <= k; i++)
{
scanf("%d%d", &x, &y);
x--;
y--;
g[i][0] = x;
g[i][1] = y;
mat[x][y] = '0' + i;
}
if (!bfs(0))
{
printf("-1\n");
}
else
{
FF(i, 1, k + 1) bfs(i);
printf("%d\n", solve());
}
}
return 0;
}

本文介绍了一种解决2013年杭州现场比赛B题的方法,通过广度优先搜索(BFS)进行预处理,然后使用深度优先搜索(DFS)或旅行商问题(TSP)算法来求解最短路径问题。该方法适用于在一个由字符矩阵表示的地图中寻找特定目标的场景。
839

被折叠的 条评论
为什么被折叠?



