题目:点击打开链接
试了各种搜索,觉得一定是搜索姿势不对,一定能搜出来,嗯,一定能·····
先从门反向bfs·····不对,路线要最优·····
那就每个人bfs一遍到每个门的最短时间,再动态规划吧······算了,看书还是·····
总的来说思想就是时间t内某个人能到达某一扇门就建一条边,然后求t对应的最大匹配,自增t,当t为n*m还不能救出所有人认为无解;
由于最大匹配算法可以从一个初始匹配开始运行,所以当我们在求时间为 t s二分图的最大匹配时,可以把 t-1 s时求得的最大匹配作为一个初始匹配。
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#include<stdlib.h>
#include<iomanip>
#include<list>
#include<stack>
#include<memory.h>
#include<ctype.h>
using namespace std;
typedef long long ll;
#define MAX 15
#define INF (1<<30)
using namespace std;
//#define LOCAL
typedef pair<int, int> pii;
pii p[MAX*MAX], d[MAX*MAX];
vector<int> G[MAX*MAX];
const int dir[4][2] = { { 0,1 },{ 0,-1 },{ 1,0 },{ -1,0 } };
int dist[MAX][MAX][MAX][MAX], cx[MAX*MAX], cy[2 * MAX*MAX*MAX];
int n, m, cp, cd, ans;
bool vis[2 * MAX*MAX*MAX];
char map[MAX][MAX];
void bfs(int x, int y, int dist[MAX][MAX])
{
int a, b, i;
queue<pii> qi;
pii tmp;
dist[x][y] = 0;
qi.push(make_pair(x, y));
while (!qi.empty())
{
tmp = qi.front();
qi.pop();
for (i = 0; i<4; i++)
{
a = dir[i][0] + tmp.first;
b = dir[i][1] + tmp.second;
if (a >= 0 && a<n&&b >= 0 && b<m&&map[a][b] == '.'&&dist[a][b] == -1)
{
dist[a][b] = dist[tmp.first][tmp.second] + 1;
qi.push(make_pair(a, b));
}
}
}
}
void add_edge(int a, int b)
{
G[a].push_back(b);
}
bool dfs(int u)
{
int i, v;
for (i = 0; i<G[u].size(); i++)
{
v = G[u][i];
if (!vis[v])
{
vis[v] = true;
if (cy[v] == -1 || dfs(cy[v]))
{
cx[u] = v;
cy[v] = u;
return true;
}
}
}
return false;
}
void Hungary(int k)
{
int i, j;
for (i = 0; i<cp; i++)
{
if (cx[i] == -1)
{
//memset(vis,false,sizeof(vis));
for (j = 0; j<cd*k; j++) vis[j] = false;
if (dfs(i)) ans++;
}
}
}
int main()
{
int t, i, j, k;
scanf("%d", &t);
while (t--)
{
scanf("%d %d", &n, &m);
for (i = 0; i<n; i++) scanf("%s", map[i]);
cp = cd = 0;
memset(dist, -1, sizeof(dist));
for (i = 0; i<n; i++)
{
for (j = 0; j<m; j++)
{
if (map[i][j] == '.') p[cp++] = make_pair(i, j);
else if (map[i][j] == 'D')
{
d[cd++] = make_pair(i, j);
bfs(i, j, dist[i][j]);
}
}
}
if (cp == 0)
{
printf("0\n");
continue;
}
ans = 0;
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
for (k = 1; k<n*m; k++)
{
for (i = 0; i<cp; i++)
{
for (j = 0; j<cd; j++)
{
if (dist[d[j].first][d[j].second][p[i].first][p[i].second] != -1 && dist[d[j].first][d[j].second][p[i].first][p[i].second] <= k)
add_edge(i, j + cd*(k - 1));
}
}
Hungary(k);
if (ans == cp)
{
printf("%d\n", k);
break;
}
}
if (k == n*m) printf("impossible\n");
for (i = 0; i<cp; i++) G[i].clear();
}
}