题目链接:点击查看

题目大意:给出一个n*n的实验室,其中有一些安全的核反应堆,我们视为墙,还有一个出了故障的核反应堆,会在t秒之后爆炸,出故障的反应堆会扩散毒气,毒气在每个时间单位都会向相邻的方格扩散一个单位,现在有数个科学家以及数个安全胶囊,如果科学家可以在毒气扩散以及核反应堆爆炸之前到达安全气囊,则可以获救,其余情况都会死亡,现在规定科学家的动作如下:

  1. 每个时间单位都可以向相邻的格子移动一个单位
  2. 不可以进入毒气的区域
  3. 每个格子同时可以容纳无数个科学家
  4. 每个安全胶囊只能容纳一个科学家

在满足以上所有条件的情况下,求在核反应堆爆炸之前,最多能有多少个科学家获救

题目分析:这个题目一方面是要求一个最大值,换种说法就是要求一种最优方案,但是这个方案中的每一个科学家的决策都会对其他科学家产生影响,所以不能单纯的考虑最短路的问题,既然是要在全局情况下考虑最优方案,我们不妨用网络流来解决,在读入数据后可以预处理出dp[time][x][y][xx][yy]数组,表示在time时间时可以从点(x,y)到达点(xx,yy),同时可以更简化一下,也就是预处理出在给定时间t之前,能否从点(x,y)到达点(xx,yy),这样就可以直接建图了:

  1. 源点->每个科学家,流量为当前格子科学家的数量
  2. 每个科学家->可到达的安全胶囊,流量为无穷大
  3. 每个安全胶囊->汇点,流量为当前格子安全胶囊的数量

最大流的建图比较简单,这道题目麻烦就麻烦在该如何预处理,可以用dfs和bfs,以及一点简单的动态规划

有一个细节需要注意一下,就是当某个格子(x,y)在第k秒时才被毒气扩散到,那么这个格子是可以进入的,但如果这个格子在k秒之前就被毒气扩散到了,那么这个格子才是不可行的,这个细节对应着dfs中何时该跳出

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=210;struct Edge
{int to,w,next;
}edge[N*N];//边数const int b[4][2]={0,1,0,-1,1,0,-1,0};int n,t,st=N-1,ed=st-1,cap[15][15],sci[15][15],maze[65][15][15],head[N],cnt;//maze[time][x][y]:在time时间下点(x,y)的状态:0->安全 1->墙 2->毒气bool vis[15][15],dp[65][15][15][15][15];//dp[time][x][y][xx][yy]:在time时间时能否从点(x,y)到达点(xx,yy)void addedge(int u,int v,int w)
{edge[cnt].to=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].w=0;//反向边边权设置为0edge[cnt].next=head[v];head[v]=cnt++;
}int d[N],now[N];//深度 当前弧优化bool bfs(int s,int t)//寻找增广路
{memset(d,0,sizeof(d));queue<int>q;q.push(s);now[s]=head[s];d[s]=1;while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(d[v])continue;if(!w)continue;d[v]=d[u]+1;now[v]=head[v];q.push(v);if(v==t)return true;}}return false;
}int dinic(int x,int t,int flow)//更新答案
{if(x==t)return flow;int rest=flow,i;for(i=now[x];i!=-1&&rest;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(w&&d[v]==d[x]+1){int k=dinic(v,t,min(rest,w));if(!k)d[v]=0;edge[i].w-=k;edge[i^1].w+=k;rest-=k;}}now[x]=i;return flow-rest;
}int solve(int st,int ed)
{int ans=0,flow;while(bfs(st,ed))while(flow=dinic(st,ed,inf))ans+=flow;return ans;
}int get_id(int x,int y,int k)//science:0 capsule:1
{return (x-1)*n+y+k*n*n;
}void dfs(int x,int y,int xx,int yy,int step)
{vis[xx][yy]=true;dp[step][x][y][xx][yy]=true;if(step>=t||maze[step][xx][yy])return;for(int k=0;k<4;k++){int nx=xx+b[k][0];int ny=yy+b[k][1];if(nx<=0||ny<=0||nx>n||ny>n)continue;if(vis[nx][ny])continue;if(maze[step][nx][ny])continue; dfs(x,y,nx,ny,step+1);}
}void init()
{memset(now,0,sizeof(now));memset(head,-1,sizeof(head));cnt=0;for(int time=1;time<=t;time++)//首先预处理出时间与(x,y)的关系{for(int x=1;x<=n;x++){for(int y=1;y<=n;y++){if(maze[time-1][x][y])maze[time][x][y]=maze[time-1][x][y];else{for(int k=0;k<4;k++){int xx=x+b[k][0];int yy=y+b[k][1];if(xx<=0||yy<=0||xx>n||yy>n)continue;if(maze[time-1][xx][yy]==2)maze[time][x][y]=2;}}}}}for(int i=1;i<=n;i++)//预处理出dp数组{for(int j=1;j<=n;j++){if(sci[i][j]){memset(vis,false,sizeof(vis));dfs(i,j,i,j,0);}}}for(int i=1;i<=t;i++)for(int x=1;x<=n;x++)for(int y=1;y<=n;y++)for(int xx=1;xx<=n;xx++)for(int yy=1;yy<=n;yy++)//将dp数组的状态统一到时间t下,方便操作dp[i][x][y][xx][yy]|=dp[i-1][x][y][xx][yy];
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);scanf("%d%d",&n,&t);for(int i=1;i<=n;i++){char s[15];scanf("%s",s+1);for(int j=1;j<=n;j++){if(isdigit(s[j]))sci[i][j]=s[j]-'0';else if(s[j]=='Y')maze[0][i][j]=1;else if(s[j]=='Z')maze[0][i][j]=2;}}for(int i=1;i<=n;i++){char s[15];scanf("%s",s+1);for(int j=1;j<=n;j++){if(isdigit(s[j]))cap[i][j]=s[j]-'0';}}init();for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(sci[i][j])addedge(st,get_id(i,j,0),sci[i][j]);if(cap[i][j])addedge(get_id(i,j,1),ed,cap[i][j]);}}for(int x=1;x<=n;x++)for(int y=1;y<=n;y++)for(int xx=1;xx<=n;xx++)for(int yy=1;yy<=n;yy++)if(sci[x][y]&&cap[xx][yy]&&dp[t][x][y][xx][yy])addedge(get_id(x,y,0),get_id(xx,yy,1),inf);printf("%d\n",solve(st,ed));return 0;
}

CodeForces - 78E Evacuation(最大流)相关推荐

  1. Codeforces 884F Anti-Palindromize 费用流

    题意 定义"反回文串"为一个字符串 S[1..|S|] S [ 1.. | S | ] S[1..|S|],对于任意 1<=i<=|S| 1 <= i <= ...

  2. SCAU-春季训练-不应该啊(怎么这么菜。。。)

    2021/3/14 春季训练2(难度div2d) 反思:(赛前,看什么crt,赛时满脑子都是线性方程组,....................................) 最近表现都不太好.. ...

  3. BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=3836 (Codeforces) http://codeforces.com ...

  4. CodeForces 164C Machine Programming 费用流

    Machine Programming 题目连接: http://codeforces.com/problemset/problem/164/B Descriptionww.co One remark ...

  5. Codeforces 362E Petya and Pipes 费用流建图

    题意: 给一个网络中某些边增加容量,增加的总和最大为K,使得最大流最大. 费用流:在某条边增加单位流量的费用. 那么就可以2个点之间建2条边,第一条给定边(u,v,x,0)这条边费用为0 同时另一条边 ...

  6. CodeForces - 1426E Rock, Paper, Scissors(最小费用最大流+最大费用最大流)

    题目链接:点击查看 题目大意:A 和 B 在玩石头剪刀布,A 会出 a1 次石头,a2 次剪刀,a3 次布,同理 B 会出 b1 次石头,b2 次剪刀,b3 次布,若对战顺序是可以进行决定的,问 A ...

  7. CodeForces - 1252L Road Construction(基环树+有源汇有上下界的最大流)

    题目链接:点击查看 题目大意:给出 n 个节点,再给出 n 个出边,保证所有的边能将 n 个点连通,每条出边可以用 m[ i ] 种材料选择其一建造,然后有 k 个工人,每个工人只可以使用一种材料建造 ...

  8. CodeForces - 1360G A/B Matrix(最大流)

    题目链接:点击查看 题目大意:给出一个 n * m 大小的空矩阵,要求在某些位置放置 1 ,其余位置放置 0 ,使得每行都有恰好 a 个 1 ,且每列恰好有 b 个 1 ,给出一种构造方案或者判断是否 ...

  9. CodeForces - 1354F Summoning Minions(最大费用最大流)

    题目链接:点击查看 题目大意:给出 n 个仆人可以召唤,场上最多可以同时存在 k 个仆人,每个仆人带有一个属性 a 和属性 b ,仆人本身的价值为 a[ i ] ,当召唤出仆人 i 后,场上的所有仆人 ...

最新文章

  1. ElasticSearch5.5.1插件分类
  2. java is开头版本解决_eclipse指定jdk版本启动,解决Version XXXX of the JVM is not
  3. python 数字大小排序_python list字符按数字大小排序
  4. 【Spark】Spark的Kryo序列化
  5. Java基础视频笔记(四):泛型
  6. 2021年赚钱的建议
  7. 数据挖掘工具---Spark SQL使用
  8. mysql 插入数据报错,a foreign key constraint fails
  9. 用c语音打一个简单的a+b
  10. MS8413光纤同轴解码芯片
  11. STM32F407传输OV2640视频数据并在PC端显示
  12. 前端可以做的SEO搜索引擎优化(摘取)
  13. 经典IIR数字滤波器设计一般步骤的总结
  14. Linux系统配置文件 /etc/sysconfig详解
  15. 利用线性回归实现股票预测分析
  16. 分布式电源接入对配电网影响的研究附Matlab代码
  17. 2023西湖论剑——misc——MP3
  18. MySQL学习笔记 05、触发器、存储过程、存储函数、定时任务
  19. 彻底理解对象内存分配及Minor GC和Full GC全过程
  20. 荣耀9i升级android10,华为正式宣布:荣耀9i等5款机型即将升级EMUI 9.0!

热门文章

  1. python casefold lower_Python学习之路(2)——字符串方法casefold和lower的区别(Python3.5)-Go语言中文社区...
  2. 使用Zookeeper实现leader选举-LeaderSelector
  3. 简单了解RestTemplate消息读取的转化
  4. MyBatis关键配置-创建会话工厂
  5. 选择Bean 实例化策略
  6. 注册注解BeanDefinition
  7. Redis中的客户端Sharding
  8. 定义和使用含有泛型的接口
  9. shiro认证与授权:基于ini的用户授权
  10. StringBuilder的toString方法