(http://www.elijahqi.win/2017/11/23/luogu2472bzoj1066-scoi2007%E8%9C%A5%E8%9C%B4/)
题目背景
07四川省选
题目描述
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。
每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
输入输出格式
输入格式:
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
输出格式:
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
输入输出样例
输入样例#1: 复制
5 8 2
00000000
02000000
00321100
02000000
00000000
……..
……..
..LLLL..
……..
……..
输出样例#1: 复制
1
说明
100%的数据满足:1<=r, c<=20, 1<=d<=3
建边 每个柱子拆点 用来限制跳跃次数
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
int h[1000],num=1;
int r,c,d,ans1,mp[22][22],level[1000];char s1[22];
struct node{
int x,y,next,z;
}data[644000];
inline void insert1(int x,int y,int z){
data[++num].y=y;data[num].z=z;data[num].next=h[x];h[x]=num;data[num].x=x;
data[++num].y=x;data[num].z=0;data[num].next=h[y];h[y]=num;data[num].x=y;
}
inline int calc(int i,int j,int op){return (i-1)*c*2+(j-1)*2+op;}
inline bool bfs(){
memset(level,0,sizeof(level));queue<int>q;q.push(0);level[0]=1;
while (!q.empty()){
int x=q.front();q.pop();
for (int i=h[x];i;i=data[i].next){
int y=data[i].y,z=data[i].z;
if (level[y]||!z) continue;q.push(y);
level[y]=level[x]+1;if (y==900) return true;
}
}return false;
}
inline bool check(int x,int y,int x1,int y1){
if (!mp[x1][y1]) return false;
if ((x1-x)*(x1-x)+(y1-y)*(y1-y)>d*d) return false;else return true;
}
int dfs(int x,int s){
if (x==900) return s;int ss=s;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y,z=data[i].z;
if (level[x]+1==level[y]&&z){
int xx=dfs(y,min(z,s));
s-=xx;data[i].z-=xx;data[i^1].z+=xx;
if (!s) return ss;
}
}return ss-s;
}
int main(){
freopen("2472.in","r",stdin);
scanf("%d%d%d",&r,&c,&d);
for (int i=1;i<=r;++i){
scanf("%s",s1+1);
for (int j=1;j<=c;++j) mp[i][j]=s1[j]-'0';
}
for (int i=1;i<=r;++i){
scanf("%s",s1+1);
for (int j=1;j<=c;++j) if (s1[j]=='L') insert1(0,calc(i,j,1),1),ans1++;
}
for (int i=1;i<=r;++i){
for (int j=1;j<=c;++j){
if (!mp[i][j]) continue;
for (int x=1;x<=r;++x){
for (int y=1;y<=c;++y){
if (i==x&&j==y) continue;
if (check(i,j,x,y)){
insert1(calc(i,j,2),calc(x,y,1),inf);
}
}
}
if (i<=d||abs(r-i+1)<=d||j<=d||abs(c-j+1)<=d)insert1(calc(i,j,2),900,inf);
}
}int ans=0;
for (int i=1;i<=r;++i)
for (int j=1;j<=c;++j)
if (mp[i][j])insert1(calc(i,j,1),calc(i,j,2),mp[i][j]);
// for (int i=2;i<=num;++i) printf("%d %d %d\n",data[i].x,data[i].y,data[i].z);
while(bfs())
ans+=dfs(0,inf);
printf("%d",ans1-ans);
return 0;
}