您的位置:首页 > 产品设计 > UI/UE

UVA Live 6557 Stampede! (uestc oj 871) 最大流+二分

2017-06-29 13:03 477 查看


E - Stampede!


Time Limit: 3000/1000MS (Java/Others)     


Memory Limit: 131072/131072KB (Java/Others)


You have an n×n game
board. Some squares contain obstacles, except the left- and right-most columns which are obstacle-free. 
The left-most column is filled with your n pieces, 1 per
row. Your goal is to move all your pieces to the right-most column as quickly
 as possible. 
In a given turn, you can move each piece 
N
S
E
,
or 
W
 one space, or leave that piece in place. 
A piece cannot move onto a square containing an obstacle, nor may two pieces move to the same square on the same turn.
 All pieces move simultaneously, so one may move to a location currently occupied by another piece so long as that piece itself moves 
elsewhere at the same time.
Given n and
the obstacles, determine the fewest number of turns needed to get all your pieces to the right-hand side of the board.


Input

Each test case starts with a positive integer n indicating
the size of the game board, with n≤25.
Following this will be n lines
containing
 

ncharacters
each. 
If the jth character
in the ith line
is an 
X
, then there is an obstacle in board location i,j;
otherwise this character will be a 
.
 indicating
 no obstacle. 
There will never be an obstacle in the 0th or (n−1)st column
and there will always be at least one obstacle-free path between these 
two columns.
A line containing a single 0 will
terminate input.


Output

For each test case output the minimum number of turns to move all the pieces from the left side of the board to the right side.


Sample input and output

Sample InputSample Output
5
.....
.X...
...X.
..X..
.....
5
.X...
.X...
.X...
.XXX.
.....
0

Case 1: 6
Case 2: 8


Source

2013 East Central Regional Contest

给你一个地图,.表示可以走,X表示不能走,左边n个点开始时有n个人,问从左边n个点走到右边n个点最短时间是多少。
每个点任意时刻仅可容纳一个人。

网络流。
左边n个点到右边n个点,显然是一个多源点多汇点题目。题目要求每个点任意时刻只能有一个人,那么我们建图时可以二分时间t,
将一个点拆成t+1个点,分别表示时刻0,1,...t的该点。之后,根据所给地图建图,跑最大流就好了。
时限应该是20s,坑爹的oj...害的我跑到codeforces gym去测这题

#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <string.h>
using namespace std;
const int maxn=500005,maxk=5000005,inf=0x3f3f3f3f;
int num=0,current[maxn],head[maxn],r[maxn],dirx[4],diry[4];
char map[28][28];
struct Edge{
int to,flow,pre;
} edge[maxk];

void addedge(int from,int to,int flow) {
edge[num]=(Edge){to,flow,head[from]};
head[from]=num++;
edge[num]=(Edge){from,0,head[to]};
head[to]=num++;
}

bool bfs(int n) {
queue<int> q;
memset(r,-1,sizeof(r));
q.push(0);
r[0]=0;
while (!q.empty()) {
int now=q.front();
q.pop();
for (int i=head[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
if (r[to]==-1&&edge[i].flow>0) {
r[to]=r[now]+1;
q.push(to);
}
}
}
return r
!=-1;
}

int dfs(int now,int flow,int des) {
if (now==des) return flow;
int f;
for (int i=current[now];i!=-1;i=edge[i].pre) {
int to=edge[i].to;
current[now]=i;
if (edge[i].flow>0&&r[to]==r[now]+1) {
if (f=dfs(to,min(flow,edge[i].flow),des)) {
edge[i].flow-=f;
edge[i^1].flow+=f;
return f;
}
}
}
return 0;
}

int dinic(int n) {
int i,f,sum=0;
while (bfs(n)) {
memcpy(current,head,sizeof(head));
while (f=dfs(0,inf,n)) sum+=f;
}
//	cout << n << ' ' << sum << endl;
return sum;
}

void buildgraph(int mid,int n) {
num=0;
memset(head,-1,sizeof(head));
int i,k=0,l,j,m;
for (i=1;i<=n;i++) {
addedge(0,(i-1)*mid*n+1,1);
addedge(i*n*mid,n*n*mid+1,1);
for (j=1;j<=n;j++) {
k++;
for (l=1;l<mid;l++) {
addedge((k-1)*mid+l,(k-1)*mid+l+1,1);
if (map[i][j-1]=='.')
for (m=0;m<4;m++) {
int nowx=i+dirx[m],nowy=j+diry[m];
if (map[nowx][nowy-1]=='.'&&nowx>0&&nowx<=n&&nowy>0&&nowy<=n) {
int u=(nowx-1)*n+nowy;
addedge((k-1)*mid+l,(u-1)*mid+l+1,1);
}
}
}
}
}
}

int solve(int n) {
int l=1,r=n*n+5,mid,ans=-1;
while (l<=r) {
mid=(l+r)/2;
buildgraph(mid,n);
if (dinic(mid*n*n+1)>=n) {
ans=mid;
r=mid-1;
} else l=mid+1;
}
return ans-1;
}

int main() {
int n,t=0,i;
scanf("%d",&n);
dirx[0]=dirx[1]=diry[2]=diry[3]=0;
dirx[2]=1;dirx[3]=-1;
diry[0]=1;diry[1]=-1;
while (n) {
t++;
for (i=1;i<=n;i++) {
scanf("%s",map[i]);
}
int ans=solve(n);
printf("Case %d: %d\n",t,ans);
scanf("%d",&n);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络流 图论