bzoj1066(网络流)
2016-07-28 17:42
603 查看
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃
到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石
柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不
变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个
石柱上。
不是很难的建模,就是注意加边的时候一些细节,不要加重复也不要少加
一个点的出点要连上它所能到达的点的入点,注意这里并不是只能往下和右走,而是可以向四个方向走,那么就是要向四个方向都连,//就是wa在这里了
a的出点连b的入点,b的出点连a的入点,实际上既然可以向四个方向走,那么就可以向四个方向都连,每一个点
注:如果题目允许向各个方向(向右向下,向右向上,向左向下,向左向上)走,那么就是每个点向各个方向连,每个点只连单向的四种,别的点也连这样的就成一对了,就覆盖所有情况了
如果只是向右和向下走,那么一个点只与它下面和右边的点连,只有一种情况
(嗷嗷嗷,好乱好乱~)
总之,关于这个棋盘里面连边方向的问题,需要仔细想一想,确保考虑好所有的情况
总结
1:在棋盘问题中,关于根据移动方向连边的问题需要仔细地想一想,保证可以连的那些方向的边可以不重不漏。
2:这道题就是很经典的网络流,一个流代表一个方案(一个流代表一个青蛙跑出去),且有一些约束,一个石头只能到几次,在通过各种技巧来进行处理这些约束就可以了。(这里限制流过几只青蛙,是通过分点,连边容量为限制量的技巧来处理的,也是很经典)
到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石
柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不
变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个
石柱上。
不是很难的建模,就是注意加边的时候一些细节,不要加重复也不要少加
一个点的出点要连上它所能到达的点的入点,注意这里并不是只能往下和右走,而是可以向四个方向走,那么就是要向四个方向都连,//就是wa在这里了
a的出点连b的入点,b的出点连a的入点,实际上既然可以向四个方向走,那么就可以向四个方向都连,每一个点
注:如果题目允许向各个方向(向右向下,向右向上,向左向下,向左向上)走,那么就是每个点向各个方向连,每个点只连单向的四种,别的点也连这样的就成一对了,就覆盖所有情况了
如果只是向右和向下走,那么一个点只与它下面和右边的点连,只有一种情况
(嗷嗷嗷,好乱好乱~)
总之,关于这个棋盘里面连边方向的问题,需要仔细想一想,确保考虑好所有的情况
#include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<cmath> #include<queue> #include<iostream> #define debug(x) cout<<#x<<"="<<endl using namespace std; const int inf=0x3f3f3f3f; const int N=1009; const int len[5]={0,2,5,10,14};//对于每一个d,所能连的最大限度 const int qx[14]={-1,0,0,-1,-2,0,-1,-2,-3,-2,0,-1,-3,-4}; const int qy[14]={0,-1,-2,-1,0,-3,-2,-1,0,-2,-4,-3,-1,0};//距离范围内所能到达的点坐标差,然后向四个方向连 int r,c,d,s,t; int id1[22][22],id2[22][22],map[22][22]; int ok(int x,int y) { if (x<1||x>r||y<1||y>c) return 1; if (map[x][y]==0) return 2; return 3; } int lev ,head ,tot,cur ; struct aa { int cap,to,pre,flow; }edge[50009]; void addedge(int x,int y,int z) { edge[++tot].to=y;edge[tot].cap=z;edge[tot].pre=head[x];head[x]=tot; edge[++tot].to=x;edge[tot].cap=0;edge[tot].pre=head[y];head[y]=tot; } bool bfs() { memset(lev,0,sizeof(lev)); queue<int> q;q.push(s);lev[s]=1; while (!q.empty()) { int u=q.front();q.pop(); for (int i=head[u];i;i=edge[i].pre) if (edge[i].cap>edge[i].flow&&lev[edge[i].to]==0) { lev[edge[i].to]=lev[u]+1; if (edge[i].to==t) return true; q.push(edge[i].to); } } return false; } int dfs(int u,int maxflow) { if (u==t||maxflow==0) return maxflow; int ans=0; for (int &i=cur[u];i;i=edge[i].pre) if (lev[edge[i].to]==lev[u]+1) { int flow=dfs(edge[i].to,min(maxflow,edge[i].cap-edge[i].flow)); ans+=flow; maxflow-=flow; edge[i].flow+=flow; edge[((i-1)^1)+1].flow-=flow; if (maxflow==0) return ans; } return ans; } int work() { int ans=0; while (bfs()) { for (int i=s;i<=t;i++) cur[i]=head[i]; ans+=dfs(s,inf); } return ans; } int main() { scanf("%d%d%d",&r,&c,&d); int bj=0,total=0; for (int i=1;i<=r;i++) for (int j=1;j<=c;j++) id1[i][j]=++bj,id2[i][j]=++bj; char ch[30]; s=0,t=bj+1; for (int i=1;i<=r;i++) { scanf("%s",ch); for (int j=0;j<strlen(ch);j++) { if (ch[j]>'0') addedge(id1[i][j+1],id2[i][j+1],ch[j]-'0'); map[i][j+1]=ch[j]-'0'; } } for (int i=1;i<=r;i++) { scanf("%s",ch); for (int j=0;j<strlen(ch);j++) if (ch[j]=='L') addedge(s,id1[i][j+1],1),total++; } for (int i=1;i<=r;i++) for (int j=1;j<=c;j++) { bool o=false; for (int l=0;l<len[d];l++) { int x=ok(i+qx[l],j+qy[l]); if (x==1) o=true; if (x==3) addedge(id2[i][j],id1[i+qx[l]][j+qy[l]],inf); if (qy[l]!=0) { x=ok(i+qx[l],j-qy[l]); if (x==1) o=true; if (x==3) addedge(id2[i][j],id1[i+qx[l]][j-qy[l]],inf); } if (qx[l]!=0)//注意特殊情况的处理,就是如果在x坐标相同,就不能通过这个找对称点,他的对称点就是原来这个点 { x=ok(i-qx[l],j+qy[l]); if (x==1) o=true; if (x==3) addedge(id2[i][j],id1[i-qx[l]][j+qy[l]],inf); } if (qx[l]!=0&&qy[l]!=0) { x=ok(i-qx[l],j-qy[l]); if (x==1) o=true; if (x==3) addedge(id2[i][j],id1[i-qx[l]][j-qy[l]],inf); } } if (o) addedge(id2[i][j],t,inf); } printf("%d",total-work()); return 0; }
总结
1:在棋盘问题中,关于根据移动方向连边的问题需要仔细地想一想,保证可以连的那些方向的边可以不重不漏。
2:这道题就是很经典的网络流,一个流代表一个方案(一个流代表一个青蛙跑出去),且有一些约束,一个石头只能到几次,在通过各种技巧来进行处理这些约束就可以了。(这里限制流过几只青蛙,是通过分点,连边容量为限制量的技巧来处理的,也是很经典)
相关文章推荐
- Listview 设置两列异步加载网络图片,结果出现图片显示错位
- 关于网络字节序和主机字节序的转换
- AngularJS下$http上传文件(AngularJS file upload/post file)
- 计算机网络Socket编程之TCP协议
- 男子轻信网上兼职被骗 寻“网络警察”求助再陷骗局
- 孙鑫 lesson14 network
- 数据挖掘——SVM和神经网络
- 无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(二)
- 利用iptables实现基于端口的网络流量统计
- 无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(一)
- HttpClient自动处理Gzip,Deflate压缩
- HTTP状态码详解
- 网络通信
- 牛客网 7-28 网络基础 操作系统 编译与体系结构 30题知识点总结
- CentOS网络配置
- [转] 携程App网络服务通道治理和性能优化@2016
- Redhat 7.1使用CentOS 7 的Yum网络源
- BP神经网络python简单实现
- asp.net XMLHttpRequest 进度条以及lengthComputable always false的解决办法
- HTTP协议