二分 Evacuation

来源:互联网 发布:thinkphp开发cms 编辑:程序博客网 时间:2024/06/18 08:26

题目:点击打开链接

试了各种搜索,觉得一定是搜索姿势不对,一定能搜出来,嗯,一定能·····

先从门反向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();}}






原创粉丝点击