解题思路:本来这道题可以用二分来做,更加直观一些。但是挑战上又介绍了优化的方法,所以试了一下。一些重要的细节代码里注释了。大概思路这里讲一下:就是随着时间的增加来添加点(不同时刻的门)和边。然后添加的新的时刻的门去和人进行匹配,如果匹配上了就代表在这个时刻这扇门可以送走一个人。随着时间的增加,新时刻的门继续把剩余的人给匹配掉。直至全部人匹配完,或者时间到为止。这里的时间最长是n*m,即输入矩阵的大小。因为假使只有一扇门,其余位置全是人,那n*m的时间也可以把人都给送出去了。
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
struct node
{
int x,y;
node(int x,int y):x(x),y(y){}
node(){
}
};
char s[13][13],n,m;
int dis[13][13][13][13],match[50009],chk[50009];
int dx[4]={-1,0,0,1},dy[4]={0,1,-1,0};
vector<node> p1,p2;
vector<int> g[50008];
void bfs(int x,int y,int d[13][13])
{
queue<node> q;
node t;
d[x][y]=0;
q.push(node(x,y));
while(!q.empty())
{
t=q.front();
q.pop();
for(int k=0;k<4;k++)
{
int tx=t.x+dx[k];
int ty=t.y+dy[k];
if(tx>=0&&tx<n&&ty>=0&&ty<m&&s[tx][ty]=='.'&&d[tx][ty]<0)
{
d[tx][ty]=d[t.x][t.y]+1;
q.push(node(tx,ty));
}
}
}
}
void add_edge(int u,int v)
{
g[u].push_back(v);
}
int dfs(int u)
{
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(!chk[v])
{
chk[v]=1;
int t=match[v];
match[v]=u;
if(t==-1||dfs(t))
return 1;
match[v]=t;
}
}
return 0;
}
void solve()
{
int t1=p1.size(),t2=p2.size();
if(t2==0)
{
printf("0\n");
return;
}
for(int i=0;i<t1;i++)
{
for(int j=0;j<t2;j++)
{
if(dis[p1[i].x][p1[i].y][p2[j].x][p2[j].y]>0)//这一步必须有,不然那些与世隔绝的人的-1会造成内存错位
for(int k=dis[p1[i].x][p1[i].y][p2[j].x][p2[j].y];k<=n*m;k++)
{
add_edge((k-1)*t1+i,n*m*t1+j);//(k-1)*t1+i表示第k时刻第i个门 , n*m*t1+j代表第j个人。
//这里的意思是第j个人不考虑拥堵时是可以从k时刻第i个门出去的。
}
}
}
//以下是经典的匈牙利算法
memset(match,-1,sizeof(match));
int num=0;
for(int v=0;v<n*m*t1;v++)
{
memset(chk,0,sizeof(chk));
if(dfs(v))
{
num++;
if(num==t2)
{
printf("%d\n",v/t1+1);
return;
}
}
}
printf("impossible\n");
}
int main()
{
//freopen("t.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
getchar();
for(int i=0;i<n;i++)
{
gets(s[i]);
//printf("%s\n",s[i]);
}
p1.clear();
p2.clear();
memset(dis,-1,sizeof(dis));
for(int i=0;i<50008;i++) g[i].clear();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j]=='D')
{
p1.push_back(node(i,j));
bfs(i,j,dis[i][j]);
}else
if(s[i][j]=='.')
{
p2.push_back(node(i,j));
}
}
}
solve();
}
return 0;
}