Escaping | ||||||
| ||||||
Description | ||||||
One day, Large cruise ”Wu Kong” at sea. The station is represented by a square n*n divided into 1*1 blocks. Unfortunately , ” Wu Kong” hit an iceberg .It will sink after t minutes ,then every people die. However, there will be some life-saving equipment in some rooms(not only one), People from one room to reach another adjacent room (only four) needs one minute .If the people on board to get these life-saving devices so that they will survive, find the greatest number of people can survive. | ||||||
Input | ||||||
The first line contains two integers n and t (2≤n≤10, 1≤t≤10). Each of the next n lines contains n integers(0<=A[i][j]<=9).the people number at this time. Each of the next n more lines contains n integers, Indicates that the room have the number of life-saving equipment(0<=B[i][j]<=9). | ||||||
Output | ||||||
Print a single number — the maximum number of people who will be saved. | ||||||
Sample Input | ||||||
3 3 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 3 | ||||||
Sample Output | ||||||
2 | ||||||
Source | ||||||
CPC23 2014-5 | ||||||
Author | ||||||
Li jinmeng |
题目大意:
现在有一艘船撞上了冰山,还有t秒所有人都会被淹死,船可以用一个n*n的图来表示,其中第一个输入的矩阵表示哪些地方有多少人,第二个输入的矩阵表示哪些地方有逃生的工具,只要人拿到了逃生工具就不会被淹死,问最多能够生存下来多少人。人每一秒都可以向周围四个方向移动一个格子。(上下左右)
思路:
1、很典型的多重匹配的模型,我比较喜欢跑最大牛,说以这里给出最大牛的做法。
2、建图:
①建立源点S,将其连入各个有人的点,其容量为各个点有的人数的个数。
②建立汇点T,将各个有逃生工具的点连入汇点T,其容量为各个点有的逃生工具的数量。
③对应将有人的地方和有逃生工具的地方做一个曼哈顿距离,其如果小于等于t,那么对应这个人就可以拿到这个工具。所以将这个有人的点连入有工具的点,容量设定为INF.
3、建好图之后直接跑最大流即可。这里最大流==多重匹配最大匹配数。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
int from;
int to;
int w;
int next;
}e[150*150*150];
int a[150][150];
int b[150][150];
int divv[150*150];
int cur[150*150];
int head[150*150];
int n,t,ss,tt,cont;
void add(int from,int to,int w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
void Getmap()
{
cont=0;
ss=n*n*2+1;
tt=ss+1;
memset(head,-1,sizeof(head));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]>0)
{
add(ss,i*n+j+1,a[i][j]);
add(i*n+j+1,ss,0);
}
if(b[i][j]>0)
{
add(n*n+i*n+j+1,tt,b[i][j]);
add(tt,n*n+i*n+j+1,0);
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]>0)
{
for(int k=0;k<n;k++)
{
for(int l=0;l<n;l++)
{
if(b[k][l]>0)
{
int u=i*n+j+1;
int v=n*n+k*n+l+1;
if(abs(i-k)+abs(j-l)<=t)
{
add(u,v,0x3f3f3f3f);
add(v,u,0);
}
}
}
}
}
}
}
}
int makedivv()
{
memset(divv,0,sizeof(divv));
divv[ss]=1;
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
if(tt==u)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==0)
{
divv[v]=divv[u]+1;
s.push(v);
}
}
}
return 0;
}
int Dfs(int u,int maxflow,int tt)
{
if(u==tt)return maxflow;
int ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==divv[u]+1)
{
int f=Dfs(v,min(maxflow-ret,w),tt);
e[i].w-=f;
e[i^1].w+=f;
ret+=f;
if(ret==maxflow)return ret;
}
}
return ret;
}
void Dinic()
{
int ans=0;
while(makedivv()==1)
{
memcpy(cur,head,sizeof(head));
ans+=Dfs(ss,0x3f3f3f3f,tt);
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&t))
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%d",&b[i][j]);
}
}
Getmap();
Dinic();
}
}