这道题还是挺好想的,但我一开始还是想错了……
把每个石柱拆成两个点,一个入度,一个出度,两个点连一条容量为高度的边,这样就可以限制从此石柱上经过的蜥蜴的数量。关于蜥蜴是否单独成点,我是单独当成了一个点,貌似做麻烦了,可以直接源点连石柱,但那样我想会不会造成一些问题,貌似也没有。
虽然很水,但还是调了很久。主要问题出在建图上,我把一个点拆成了高度个点,这样无法达到上面说的限制蜥蜴经过的数量这个功能,所以WA了很久,看了题解,才突然明白,这么搞不行……
代码如下:
#include <cstdio>
#include
<cstring>
#include
<cstdlib>
#include
<iostream>
#include
<algorithm>
#include
<queue>
#define
N 25
#define
inf 1<<30
using
namespace
std;
struct
sss
{
int
x,y;
}xiyi[N
*
N];
int
n,m,S,T,d;
int
a[N][N]={
0
},num[N][N]={
0
},stonenum=
0
,xiyinum=
0
;
int
p[N*N*
5
],next[N*N*N*N*
6
],v[N*N*N*N*
6
],f[N*N*N*N*
6
],bnum=-
1
;
bool
kexing(
int
x,
int
y)
{
if
(x<
1
||x>n||y<
1
||y>m)
return
false
;
else
return
true
;
}
void
addbian(
int
x,
int
y,
int
flow)
{
bnum
++; next[bnum]=
p[x];
p[x]
=bnum; v[bnum]=y; f[bnum]=
flow;
bnum
++; next[bnum]=
p[y];
p[y]
=bnum; v[bnum]=x; f[bnum]=
0
;
}
int
dis[N*N*
5
];
bool
BFS()
{
int
i,j,k;
queue
<
int
>
q;
for
(i=
1
;i<=T;i++) dis[i]=-
1
;
dis[S]
=
0
; q.push(S);
while
(!
q.empty())
{
j
=q.front(); q.pop(); k=
p[j];
while
(k!=-
1
)
{
if
(f[k]&&dis[v[k]]==-
1
)
{
dis[v[k]]
=dis[j]+
1
;
q.push(v[k]);
}
k
=
next[k];
}
}
if
(dis[T]==-
1
)
return
false
;
else
return
true
;
}
int
DFS(
int
now,
int
change)
{
int
i,j,k,flow=
0
;
if
(now==T||change==
0
)
return
change;
k
=
p[now];
while
(k!=-
1
)
{
if
(f[k]&&dis[v[k]]==dis[now]+
1
&&(i=DFS(v[k],min(change,f[k])))>
0
)
{
f[k]
-=i; f[k^
1
]+=
i;
flow
+=i; change-=
i;
if
(change==
0
)
break
;
}
k
=
next[k];
}
dis[now]
=-
1
;
return
flow;
}
int
dinic()
{
int
ans=
0
,flow;
while
(BFS())
while
(flow=
DFS(S,inf))
ans
+=
flow;
return
ans;
}
bool
bianjie(
int
x,
int
y)
{
if
(x<=d||y<=d)
return
true
;
else
if
(n-x<d||m-y<d)
return
true
;
else
return
false
;
}
int
main()
{
int
i,j,k,x,y;
char
s[N];
scanf(
"
%d%d%d
"
,&n,&m,&
d);
S
=n*m*
3
+
1
; T=n*m*
3
+
2
;
for
(i=
1
;i<=T;i++) p[i]=-
1
;
for
(i=
1
;i<=n;i++
)
{
scanf(
"
%s
"
,s);
for
(j=
0
;j<m;j++
)
if
(s[j]!=
'
0
'
) a[i][j+
1
]=s[j]-
'
0
'
;
}
for
(i=
1
;i<=n;i++
)
{
scanf(
"
%s
"
,s);
for
(j=
0
;j<m;j++
)
if
(s[j]==
'
L
'
)
{
xiyinum
++; a[i][j+
1
]--
;
xiyi[xiyinum].x
=i; xiyi[xiyinum].y=j+
1
;
}
}
for
(i=
1
;i<=n;i++
)
for
(j=
1
;j<=m;j++
)
if
(a[i][j]>
0
)
{
stonenum
++
;
num[i][j]
=
stonenum;
}
for
(i=
1
;i<=n;i++
)
for
(j=
1
;j<=m;j++
)
if
(a[i][j]>
0
)
{
addbian(num[i][j],num[i][j]
+n*
m,a[i][j]);
if
(bianjie(i,j))
addbian(num[i][j]
+n*
m,T,inf);
for
(
int
I=-d;I<=d;I++
)
for
(
int
J=-d;J<=d;J++
)
if
(!(I==
0
&&J==
0
)&& I*I+J*J<=d*
d)
{
x
=i+I; y=j+
J;
if
(kexing(x,y)&&
a[x][y])
addbian(num[i][j]
+n*
m,num[x][y],inf);
}
}
for
(i=
1
;i<=xiyinum;i++
)
{
int
x1=xiyi[i].x,y1=
xiyi[i].y;
addbian(S,i
+n*m*
2
,
1
);
if
(bianjie(x1,y1))
addbian(i
+n*m*
2
,T,inf);
for
(
int
I=-d;I<=d;I++
)
for
(
int
J=-d;J<=d;J++
)
if
(!(I==
0
&&J==
0
)&& I*I+J*J<=d*
d)
{
x
=x1+I; y=y1+
J;
if
(kexing(x,y)&&
a[x][y])
addbian(i
+n*m*
2
,num[x][y],inf);
}
}
printf(
"
%d\n
"
,xiyinum-
dinic());
}

