题意:见挑战230页

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
int n,m,x,y;
vector<int> G[100005];
vector<int> dx,dy,px,py;
char field[15][15];
int xx[4]={-1,1,0,0},yy[4]={0,0,1,-1};
int sroad[15][15][15][15],dist[15][15];
int used[30000],match[1000000];
void add_edge(int u,int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
void bfs(int x,int y)
{
memset(dist,-1,sizeof(dist));
dist[x][y]=0;
queue<int> qx,qy;
qx.push(x);
qy.push(y);
while(!qx.empty())
{
int sx=qx.front();
int sy=qy.front();
for(int i=0;i<=3;i++)
{
int tx=sx+xx[i],ty=sy+yy[i];
if(tx>=0&&tx<n&&ty>=0&&ty<m)
if(field[tx][ty]=='.'&&dist[tx][ty]<0)
{
dist[tx][ty]=dist[sx][sy]+1;
sroad[x][y][tx][ty]=dist[tx][ty];
qx.push(tx);
qy.push(ty);
}
}
qx.pop();
qy.pop();
}
}
int dfs(int u)
{
used[u]=1;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i],w=match[v];
if(w<0||!used[w]&&dfs(w))
{
match[u]=v;
match[v]=u;
return 1;
}
}
return 0;
}
int pipei(int t)
{
int res=0;
for(int i=0;i<dx.size();i++)
{
int u=i+t*dx.size();
if(match[u]<0)
{
memset(used,0,sizeof(used));
if(dfs(u))
res++;
}
}
return res;
}
int num(int t)
{
for(int i=0;i<px.size();i++)
for(int j=0;j<dx.size();j++)
{
int renx=px[i],reny=py[i];
int menx=dx[j],meny=dy[j];
if(sroad[menx][meny][renx][reny]<=t)
add_edge(t*dx.size()+j,(n*m+10)*dx.size()+10+i);
}
return pipei(t);
}
void solve()
{
memset(match,-1,sizeof(match));
int ans=0;
for(int t=0;t<=n*m+3;t++)
{
ans+=num(t);
if(ans>=px.size())
{
cout<<t<<endl;
return;
}
}
cout<<"impossible"<<endl;
}
int main()
{
int cas;
cin>>cas;
while(cas--)
{
scanf("%d %d",&n,&m);
dx.clear();dy.clear();
px.clear();py.clear();
for(int i=0;i<=100005;i++)
G[i].clear();
for(int i=0;i<n;i++)
scanf("%s",field[i]);
memset(sroad,inf,sizeof(sroad));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
if(field[i][j]=='D')
{
dx.push_back(i);
dy.push_back(j);
bfs(i,j);
}
else if(field[i][j]=='.')
{
px.push_back(i);
py.push_back(j);
}
}
solve();
}
return 0;
}

 分析:强大的二分匹配(因为一个门一时刻只能通过一个人),这是我的做法,用的是枚举时间

不过看挑战上是直接枚举时间和门组成的二元组的点,每次dfs该点,进行一次匈牙利算法,最后再算出时间

好像程序可以简化一点,不过我的这份代码的效率比较高,排名在270多名,不过开的数组大小很关键,在这个上wa了很多次。

下面是wa代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
int n,m,x,y;
vector<int> G[1005];
vector<int> dx,dy,px,py;
char field[15][15];
int xx[4]={-1,1,0,0},yy[4]={0,0,1,-1};
int sroad[15][15][15][15],dist[15][15];
int used[150],match[10000];
void add_edge(int u,int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
void bfs(int x,int y)
{
memset(dist,-1,sizeof(dist));
dist[x][y]=0;
queue<int> qx,qy;
qx.push(x);
qy.push(y);
while(!qx.empty())
{
for(int i=0;i<=3;i++)
{
int tx=qx.front()+xx[i],ty=qy.front()+yy[i];
if(tx>=0&&tx<n&&ty>=0&&ty<m)
if(field[tx][ty]=='.'&&dist[tx][ty]<0)
{
dist[tx][ty]=dist[x][y]+1;
sroad[x][y][tx][ty]=dist[tx][ty];
qx.push(tx);
qy.push(ty);
}
}
qx.pop();
qy.pop();
}
}
int dfs(int u)
{
used[u]=1;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i],w=match[v];
//printf("%d %d\n",v,match[v]);
// printf("match: %d w:%d\n",match[v],w);
if(w<0||!used[w]&&dfs(w))
{
match[u]=v;
match[v]=u;
//printf("wwwww\n");
return 1;
}
}
return 0;
}
int pipei(int t)
{
int res=0;
for(int i=0;i<dx.size();i++)
{
int u=i+t*dx.size();
//printf("4 match:%d\n",match[0]);
if(match[u]<0)
{
memset(used,0,sizeof(used));
if(dfs(u))
res++;
}
}
// printf("res:%d\n",res);
return res;
}
int num(int t)
{
for(int i=0;i<px.size();i++)
for(int j=0;j<dx.size();j++)
{
int renx=px[i],reny=py[i];
int menx=dx[j],meny=dy[j];
if(sroad[menx][meny][renx][reny]<=t)
add_edge(t*dx.size()+j,px.size()*dx.size()+10+i);
}
//printf("3 match:%d\n",match[0]);
return pipei(t);
}
void solve()
{
memset(match,-1,sizeof(match));
//printf("1 match:%d\n",match[0]);
int ans=0;
for(int t=0;t<=n*m+3;t++)
{
ans+=num(t);
//cout<<t<<" "<<num(t)<<endl;
//printf("2 match:%d\n",match[0]);
if(ans>=px.size())
{
cout<<t<<endl;
return;
}
}
cout<<"impossible"<<endl;
}
int main()
{
int cas;
cin>>cas;
while(cas--)
{
scanf("%d %d",&n,&m);
dx.clear();dy.clear();
px.clear();py.clear();
for(int i=0;i<=500;i++)
G[i].clear();
for(int i=0;i<n;i++)
scanf("%s",field[i]);
memset(sroad,inf,sizeof(sroad));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
if(field[i][j]=='D')
{
dx.push_back(i);
dy.push_back(j);
bfs(i,j);
}
else if(field[i][j]=='.')
{
px.push_back(i);
py.push_back(j);
}
}
solve();
}
return 0;
}

  

TTTTTTTTTTTTT poj 3057 Evacuation 二分图匹配+bfs的更多相关文章

  1. POJ 3057 Evacuation 二分图匹配

    每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:10240000 ...

  2. POJ 3057 Evacuation (二分匹配)

    题意:给定一个图,然后有几个门,每个人要出去,但是每个门每个秒只能出去一个,然后问你最少时间才能全部出去. 析:初一看,应该是像搜索,但是怎么保证每个人出去的时候都不冲突呢,毕竟每个门每次只能出一个人 ...

  3. POJ3057 Evacuation 二分图匹配+最短路

    POJ3057 Evacuation 二分图匹配+最短路 题目描述 Fires can be disastrous, especially when a fire breaks out in a ro ...

  4. POJ 3057 Evacuation(二分图匹配+BFS)

    [题目链接] http://poj.org/problem?id=3057 [题目大意] 给出一个迷宫,D表示门,.表示人,X表示不可通行, 每个门每时间单位只允许一个人通过, 每个人移动一格的为一时 ...

  5. [poj] 3057 Evacuation

    原题 题目大意 墙壁"X",空区域(都是人)".", 门"D". 人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移 ...

  6. POJ 1274 裸二分图匹配

    题意:每头奶牛都只愿意在她们喜欢的那些牛栏中产奶,告诉每头奶牛愿意产奶的牛棚编号,求出最多能分配到的牛栏的数量. 分析:直接二分图匹配: #include<stdio.h> #includ ...

  7. POJ 2446 Chessboard (二分图匹配)

    题意 在一个N*M的矩形里,用1*2的骨牌去覆盖该矩形,每个骨牌只能覆盖相邻的两个格子,问是否能把每个格子都盖住.PS:有K个孔不用覆盖. 思路 容易发现,棋盘上坐标和为奇数的点只会和坐标和为偶数的点 ...

  8. POJ 3057 Evacuation(二分匹配)

    分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d ...

  9. POJ 3057 Evacuation 二分+最大流

    Evacuation 题目连接: http://poj.org/problem?id=3057 Description Fires can be disastrous, especially when ...

随机推荐

  1. (5.11)mysql高可用系列——复制中常见的SQL与IO线程故障

    关键词:mysql复制故障处理 [1]手工处理的gtid_next(SQL线程报错) 例如:主键冲突,表.数据库不存在,row模式下的数据不存在等. [1.1]模拟故障:GTID模式下的重复创建用户 ...

  2. hdfs基本文件操作

    编程实现下列要求: 1.创建一个自己姓名首字母的文件夹 2.在文件夹下创建一个hdfstext1.txt文件,项文件内输入“班级学号姓名HDFS课堂测试”的文字内容: 3.在文件夹下在创建一个好的fs ...

  3. celery异步发送邮件

    利用Django框架发送邮件的详细过程,在前两天的博客中有所记录,但是单纯的那样发邮件是有非常大的问题的,这就需要celery异步发送来解决 首先我们来看一下邮件发送的过程: Django网站先发送到 ...

  4. Design Support库中的控件

    1.NavigationView滑动菜单 2.FloatIngActionButton悬浮按钮 3.Snackbar二次交互提示的按钮 4.Coordinatorlayout,监听子控件的各种事件(加 ...

  5. PHP扩展开发01:第一个扩展

    我们先假设业务场景,是需要有这么一个扩展,提供一个叫ccvita_string的函数,他的主要作用是返回一段字符.(这个业务场景实在太假,大家就这么看看吧)对应的PHP代码可能是这样: functio ...

  6. ACM的一点基础知识

    所摘内容来自于XJTU小学期ACM培训PPT log 默认以2为底 计算机一秒可以看作1e8次 保证数据计算精度及数据所需必要大小 a=1LL*a*a%p//在计算时通过乘以1LL,临时将Int转化为 ...

  7. CentOS7部署kettle

    去官网下载kettle, 或者百度网盘下载(nnnk),解压到目录/opt/service/, 解压后的目录是data-integration kettle需要java环境才能运行,因此要安装Java ...

  8. Java分布式锁三种实现方案

    方案一:数据库乐观锁 乐观锁通常实现基于数据版本(version)的记录机制实现的,比如有一张红包表(t_bonus),有一个字段(left_count)记录礼物的剩余个数,用户每领取一个奖品,对应的 ...

  9. 目标 - 在虚拟机CentOS7中无图形界面安装Oracle11G R2版本

    参考: https://www.cnblogs.com/yejingcn/p/10278473.html centos7启动oracle su - oracle //切换到自己的oracle账户 ls ...

  10. 两种解决springboot 跨域问题的方法示例

    两种解决springboot 跨域问题的方法示例,哪种方法看情况而定,自己选择.社会Boolean哥,人狠话不多,直接上代码. 第一种实现方式:       此种方式做全局配置,用起来更方便,但是无法 ...