Leapin‘ Lizards
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1537 Accepted Submission(s): 626
Problem Description
Your platoon of wandering lizards has entered a strange room in the labyrinth you are exploring. As you are looking around for hidden treasures, one of the rookies steps on an innocent-looking stone and the room‘s floor suddenly disappears!
Each lizard in your platoon is left standing on a fragile-looking pillar, and a fire begins to rage below... Leave no lizard behind! Get as many lizards as possible out of the room, and report the number of casualties.
The pillars in the room are aligned as a grid, with each pillar one unit away from the pillars to its east, west, north and south. Pillars at the edge of the grid are one unit away from the edge of the room (safety). Not all pillars necessarily have a lizard.
A lizard is able to leap onto any unoccupied pillar that is within d units of his current one. A lizard standing on a pillar within leaping distance of the edge of the room may always leap to safety... but there‘s a catch: each pillar becomes weakened after
each jump, and will soon collapse and no longer be usable by other lizards. Leaping onto a pillar does not cause it to weaken or collapse; only leaping off of it causes it to weaken and eventually collapse. Only one lizard may be on a pillar at any given time.
Input
The input file will begin with a line containing a single integer representing the number of test cases, which is at most 25. Each test case will begin with a line containing a single positive integer n representing the number of
rows in the map, followed by a single non-negative integer d representing the maximum leaping distance for the lizards. Two maps will follow, each as a map of characters with one row per line. The first map will contain a digit (0-3) in each position representing
the number of jumps the pillar in that position will sustain before collapsing (0 means there is no pillar there). The second map will follow, with an ‘L‘ for every position where a lizard is on the pillar and a ‘.‘ for every empty pillar. There will never
be a lizard on a position where there is no pillar.Each input map is guaranteed to be a rectangle of size n x m, where 1 ≤ n ≤ 20 and 1 ≤ m ≤ 20. The leaping distance is
always 1 ≤ d ≤ 3.
Output
For each input case, print a single line containing the number of lizards that could not escape. The format should follow the samples provided below.
Sample Input
4 3 1 1111 1111 1111 LLLL LLLL LLLL 3 2 00000 01110 00000 ..... .LLL. ..... 3 1 00000 01110 00000 ..... .LLL. ..... 5 2 00000000 02000000 00321100 02000000 00000000 ........ ........ ..LLLL.. ........ ........
Sample Output
Case #1: 2 lizards were left behind. Case #2: no lizard was left behind. Case #3: 3 lizards were left behind. Case #4: 1 lizard was left behind.
题意:要你求出在nxm的地图中的蜥蜴尽量逃离之后剩下的最小量,蜥蜴出了地图边缘就算逃离成功,每个柱子如果上面有蜥蜴,那么蜥蜴离开这个柱子的时候柱子高度会减一,高度为0的时候蜥蜴就不能跳到这个上面,每个case输入n和D,D是蜥蜴能跳跃的最大距离,然后是两个n行的地图,因为不知道m大小,所以用%s输入然后计算,地图1中表示柱子的初始高度,地图2中“L”表示这个位置的柱子上有一只蜥蜴
题解:还是老办法,假设原点S和汇点T,每个蜥蜴连接原点S,边权值是1表示一只蜥蜴入场,然后每个高度大于0的柱子全部再设置一个流出点,因为题目中限制流量的是柱子,也就是点,我们把这个点作为这个流量的流入点,再设置一个流出点,连接它们并使边权值为这个点的高度,这样就能把限制从点转移到边了,我是流出点等于流入点加400,因为地图最大的点的数量是400,然后能出边界的且柱子高度大于0的点,全部连接汇点T,边权值是MAX,然后是可以跳跃的柱子之间连接起来,边权值也是MAX,MAX是一个极大值,自己尽量设大点,用来表示这是一条通路就行。
注意:网上各种喊坑:
1、输出那里看好了,英语单词的大考验--!输出的剩余数量如果是no或者1则用单数形式,大于1则用复数形式(单数 lizard was 复数 lizards were);
2、题目说柱子高度d的范围是0<=d<=3,但是有更大的值,也就是说会超过3,这里影响不大,是那些屌丝抱怨着喊出来的;
3、每个高度大于0的柱子作为流入点并额外再设置一个流出点,则柱子与柱子满足跳跃距离是要保证流出点对流入点作边,不然对于这么多代码,混乱一块则让你纠结到死;
4、这里的距离我也不知道作者是怎么想的,竟然是两点的x轴距离加上y轴距离的和;
5、这里对于第一次做这种由点来限制流量的网络流题目,看到别人博客写着“分割点”,尼玛啵什么是分割点又不讲,留下来的就是一堆在你眼里类似乱码的代码,这里我告诉你我的理解,分割点是对于由点来限制流量的情况下把这个点分成两个点,然后相连的这条边就设置为这个点的值,这样这限制流量的就不是点而是边了,这样你学过的那些东东就又能用了,嘿嘿~~~不知道对不对,但是这样理解不会有错。。
对于类似我这种懒于看字的人,我画个图,相信有点用。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define MAX 1000000001
#define Max(a,b) a>b?a:b
#define Min(a,b) a<b?a:b
#define M 1111
using namespace std;
int D,S=0,T,num,cas=1;
char s1[22][22],s2[22][22];//两个地图
struct node
{
int to,val,next;
}s[M*M];
int snum,dnum=400,hand[M],dis[M],q[M];
void setit(int from,int to,int
val)//这个线性建立点的我就不多说了,前面博客有
{
s[snum].to=to;
s[snum].val=val;
s[snum].next=hand[from];
hand[from]=snum++;
s[snum].to=from;
s[snum].val=0;
s[snum].next=hand[to];
hand[to]=snum++;
}
bool pd(int x,int y,int
n,int l)//判断当前坐标移动D之后是否出界
{
if(x<=D||y<=D)return
true;
if(n+1-x<=D||l+1-y<=D)return
true;
return false;
}
bool pddis(int x1,int y1,int
x2,int y2)//判断两坐标的x距离与y距离之和是否小于D,即他们的距离蜥蜴是否能跳跃
{
int a,b;
a=x1-x2;
b=y1-y2;
a=(a>0?a:-a);
b=(b>0?b:-b);
if(a+b<=D)return
true;
return false;
}
bool bfs()//dinic算法中bfs分层,前面博客已经写过详细的了
{
int i,j,k,l,cur,qian,hou;
memset(dis,-1,sizeof(dis));
qian=hou=0;
q[qian++]=S;
dis[S]=0;
while(qian!=hou)
{
cur=q[hou++];
if(hou>=M)hou=0;
for(i=hand[cur];i!=-1;i=s[i].next)
{
k=s[i].to;
if(s[i].val>0&&dis[k]==-1)
{
dis[k]=dis[cur]+1;
q[qian++]=k;
if(qian>=M)qian=0;
if(k==T)return
true;
}
}
}
return false;
}
int dfs(int x,int flow)//同上,前面写过详细的了
{
int i,j,k,l,cost=0;
if(x==T)return flow;
for(i=hand[x];i!=-1;i=s[i].next)
{
k=s[i].to;
if(s[i].val>0&&dis[x]+1==dis[k])
{
l=dfs(k,Min(flow-cost,s[i].val));
if(l>0)
{
cost+=l;
s[i].val-=l;
s[i^1].val+=l;
}else dis[k]=-1;
}
}
return cost;
}
void dinic()//同上
{
int i,j,k,l=num;
while(bfs())
{
k=dfs(S,MAX);
l-=k;
}
if(l==0)printf("Case
#%d: no lizard was left behind.\n",cas++);//这里就是我说的第一个坑点
else printf("Case #%d: %d %s left behind.\n",cas++,l,l==1?"lizard
was":"lizards were");
}
int main (void)
{
int t,n,m,i,j,k,l,x,y,q;
scanf("%d",&t);
while(t--&&scanf("%d%d",&n,&D))
{
snum=0;
num=0;
memset(hand,-1,sizeof(hand));
for(i=0;i<n;i++)
{
scanf("%s",s1[i]);//输入第一个地图
l=strlen(s1[i]);//不好意思,这一句忘记删除了
}
T=1001;
for(i=0;i<n;i++)
{
scanf("%s",s2[i]);输入第二个地图
for(j=0;j<l;j++)
{
q=i*l+j+1;//把地图上的点编号成1到nXm
if(s2[i][j]==‘L‘)
{
num++;
setit(S,q,1);//连接原点S跟当前点
}
if(s1[i][j]!=‘0‘)
{
setit(q,q+dnum,s1[i][j]-‘0‘);//dnum=400,q+dnum是表示q的流出点,而q直接作为流入点
for(k=i*l+j;k>0;k--)
{
x=(k-1)/l;//把编号分解成坐标
y=k-x*l-1;
if(s1[x][y]!=‘0‘&&pddis(i,j,x,y))//判断(x,y)高度和它与(i,j)的距离
{
setit(q+dnum,k,MAX);//两个柱子都能供蜥蜴跳跃且距离可以,则(i,j)流出点连接(x,y)流入点
setit(k+dnum,q,MAX);//(x,y)流出点连接(i,j)流入点
}
}
if(pd(i+1,j+1,n,l))//判断移动D距离能否出界
{
setit(q+dnum,T,MAX);//能出界则当前点的流出点连接汇点T
}
}
}
}
dinic();
}
return 0;
}
照这样每天都有收货的过下去,至少自己更自信~~
HDU--杭电--2732//POJ--2711--Leapin' Lizards--网络流