BZOJ 1066 [SCOI2007]蜥蜴(最大流)
2024-08-25 15:31:20
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1066
【题目大意】
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,
你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,
蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。
石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1
(如果仍然落在地图内部,则到达的石柱高度不变),
如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。
任何时刻不能有两只蜥蜴在同一个石柱上。
【题解】
我们将相互可达的点连线,建立源点,往有蜥蜴在的石柱连流量为1的边,
建立汇点,把能一次跳到外面的点和汇点连流量无穷的边。
拆点,将点可经过次数作为边权以限制通过,求最大流即最多能逃脱的蜥蜴数量
【代码】
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX_V=1000;
struct edge{int to,cap,rev;};
vector<edge> G[MAX_V];
int level[MAX_V],iter[MAX_V];
void add_edge(int from,int to,int cap){
G[from].push_back((edge){to,cap,G[to].size()});
G[to].push_back((edge){from,0,G[from].size()-1});
}
void bfs(int s){
memset(level,-1,sizeof(level));
queue<int> que;
level[s]=0;
que.push(s);
while(!que.empty()){
int v=que.front(); que.pop();
for(int i=0;i<G[v].size();i++){
edge &e=G[v][i];
if(e.cap>0&&level[e.to]<0){
level[e.to]=level[v]+1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f){
if(v==t)return f;
for(int &i=iter[v];i<G[v].size();i++){
edge &e=G[v][i];
if(e.cap>0&&level[v]<level[e.to]){
int d=dfs(e.to,t,min(f,e.cap));
if(d>0){
e.cap-=d;
G[e.to][e.rev].cap+=d;
return d;
}
}
}return 0;
}
int max_flow(int s,int t){
int flow=0;
for(;;){
bfs(s);
if(level[t]<0)return flow;
memset(iter,0,sizeof(iter));
int f;
while((f=dfs(s,t,INF))>0){
flow+=f;
}
}
}
vector<int> res;
char mp[30][30],MP[30][30];
int vis[30][30];
int n,m,d;
void solve(){
int s=n*m*2,t=s+1,cnt=0;
for(int i=0;i<=t;i++)G[i].clear();
for(int i=0;i<n;i++)scanf("%s",mp[i]);
for(int i=0;i<n;i++)scanf("%s",MP[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
add_edge(i*m+j,i*m+j+n*m,mp[i][j]-'0');
if(MP[i][j]=='L')add_edge(s,i*m+j,1),cnt++;
if(i<d||j<d||n-i<=d||m-j<=d)add_edge(i*m+j+n*m,t,INF);
}
}for(int i=0;i<n;i++)for(int j=0;j<m;j++){
for(int k=0;k<n;k++)for(int u=0;u<m;u++){
if(abs(i-k)+abs(u-j)<=d&&(i!=k||j!=u)){
add_edge(i*m+j+n*m,k*m+u,INF);
add_edge(k*m+u+n*m,i*m+j,INF);
}
}
}
printf("%d\n",cnt-max_flow(s,t));
}
int main(){
while(~scanf("%d%d%d",&n,&m,&d)){
solve();
}return 0;
}
最新文章
- EXCEL中多级分类汇总空白字段填充
- 25M电子琴实现
- [UE4]自定义MovementComponent组件
- 10 个强大的开源 Web 流量分析工具(转帖)
- JAVA学习Swing章节按钮组件JButton的简单学习
- [cb] Unity Editor 添加右键菜单
- Oracle 中的 TO_DATE 和 TO_CHAR 函数
- [LeetCode 110] - 平衡二叉树 (Balanced Binary Tree)
- activemq demo指南
- 49. leetcode 94. Binary Tree Inorder Traversal
- 在Windows的Dos命令中切换盘符
- PHP通过get方法获得form表单数据方法总结
- C++STL模板库适配器之优先级队列
- 单元测试如何覆盖internal的方法
- shell编写自动化安装dhcp服务
- OpenCV 对矩阵进行掩码操作
- centos系统-java -jdk 环境配置
- <;context:component-scan>;详解 转发 https://www.cnblogs.com/fightingcoding/p/component-scan.html
- android studio 汉化 个性化 美化 快速操作项目 目录
- 「CSA72」MST