【HNOI2013】切糕
【HNOI2013】切糕

Sample Input
2 2 2
1
6 1
6 1
2 6
2 6
Sample Output
6
\(P,Q,R≤40,0≤D≤R\)
参考:https://blog.csdn.net/zarxdy34/article/details/45272055
经典的有距离限制的网络流模型。
首先我们不考虑高度限制。我们直接将图建\(r+1\)层,就是每个格子\((x,y)\)拆成\(r+1\)个点。将它们串成一串,第\(i\)层的向\(i+1\)层连边,第\(i\)条边的容量就是\(v_{x,y,i}\)。然后源点向第\(1\)层的连边,第\(r+1\)层的向汇点连边。最小割就是答案。
考虑怎么将距离限制表示出来。对于所有的格子\((x,y)\),假设是第\(k\)层的图,那么我们向第\(k-d\)层的\((x,y)\)周围的点连\(\infty\)的边。
考虑这么做的合法性。两个相邻的格子\((x,y),(x',y')\),如果我们选了\(v_{x,y,k}\),也就是割断了第\(k\)层\((x,y)\)连出去的边,那么\((x',y')\)选的高度\(k'\)要\(\geq k-D\)。如果\((x',y')\)割断了\(k-D\)以下的边,那么\((x,y)\)和\((x',y')\)之间\(\infty\)的边就会实源点和汇点连通。
代码:
#include<bits/stdc++.h>
#define ll long long
#define N 45
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
const int V=N*N*N;
int n,m,r;
int D;
int v[N][N][N];
int id[N][N];
struct road {
	int to,next;
	int flow;
}s[V<<3];
int h[V],cnt=1;
void add(int i,int j,int f) {
	s[++cnt]=(road) {j,h[i],f};h[i]=cnt;
	s[++cnt]=(road) {i,h[j],0};h[j]=cnt;
}
int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
int S,T;
int dis[V];
queue<int>q;
bool bfs() {
	memset(dis,0x3f,sizeof(dis));
	q.push(S);
	dis[S]=0;
	while(!q.empty()) {
		int v=q.front();
		q.pop();
		for(int i=h[v];i;i=s[i].next) {
			int to=s[i].to;
			if(s[i].flow&&dis[to]>dis[v]+1) {
				dis[to]=dis[v]+1;
				q.push(to);
			}
		}
	}
	return dis[T]<1e9;
}
int dfs(int v,int maxf) {
	if(v==T) return maxf;
	int ret=0;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(s[i].flow&&dis[to]==dis[v]+1) {
			int dlt=dfs(to,min(maxf,s[i].flow));
			s[i].flow-=dlt;
			s[i^1].flow+=dlt;
			ret+=dlt;
			maxf-=dlt;
			if(!maxf) return ret;
		}
	}
	return ret;
}
int dinic() {
	int ans=0;
	while(bfs()) {
		while(1) {
			int tem=dfs(S,1e9);
			if(!tem) break;
			ans+=tem;
		}
	}
	return ans;
}
int main() {
	n=Get(),m=Get(),r=Get();
	D=Get();
	for(int k=1;k<=r;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				v[i][j][k]=Get();
	int tot=n*m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			id[i][j]=(i-1)*m+j;
	T=(r+1)*tot+1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			add(S,id[i][j],1e9),add(id[i][j]+r*tot,T,1e9);
	for(int k=1;k<=r;k++) {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++) {
				add((k-1)*tot+id[i][j],k*tot+id[i][j],v[i][j][k]);
				if(k>D) {
					int nxt=k-D;
					for(int d=0;d<4;d++) {
						int a=i+dx[d],b=j+dy[d];
						if(a<1||a>n||b<1||b>m) continue ;
						add((k-1)*tot+id[i][j],(nxt-1)*tot+id[a][b],1e9);
					}
				}
			}
		}
	}
	cout<<dinic();
	return 0;
}
【HNOI2013】切糕的更多相关文章
- BZOJ 3144: [Hnoi2013]切糕
		3144: [Hnoi2013]切糕 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1495 Solved: 819[Submit][Status] ... 
- bzoj 3144: [Hnoi2013]切糕 最小割
		3144: [Hnoi2013]切糕 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 681 Solved: 375[Submit][Status] ... 
- BZOJ_3144_[Hnoi2013]切糕_最小割
		BZOJ_3144_[Hnoi2013]切糕_最小割 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R ... 
- bzoj千题计划142:bzoj3144: [Hnoi2013]切糕
		http://www.lydsy.com/JudgeOnline/problem.php?id=3144 如果D=2 ,两个点,高度为4,建图如下 #include<queue> #inc ... 
- 【BZOJ3144】[HNOI2013]切糕
		[BZOJ3144][HNOI2013]切糕 题面 题目描述 经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B.出于美观考虑,小 A 希望切面能尽量光滑 ... 
- 【BZOJ 3144】 3144: [Hnoi2013]切糕 (最小割模型)
		3144: [Hnoi2013]切糕 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1764 Solved: 965 Description Inp ... 
- BZOJ3144 Hnoi2013 切糕 【网络流】*
		BZOJ3144 Hnoi2013 切糕 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的 ... 
- 【BZOJ3144】[Hnoi2013]切糕 最小割
		[BZOJ3144][Hnoi2013]切糕 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q ... 
- 3144: [Hnoi2013]切糕
		3144: [Hnoi2013]切糕 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1526 Solved: 827[Submit][Status] ... 
- bzoj3144 [HNOI2013]切糕(最小割)
		bzoj3144 [HNOI2013]切糕(最小割) bzoj Luogu 题面描述见上 题解时间 一开始我真就把这玩意所说的切面当成了平面来做的 事实上只是说相邻的切点高度差都不超过 $ d $ 对 ... 
随机推荐
- ES5、ES2015、ECMAScript6(转载)
			阮一峰博客系列: http://es6.ruanyifeng.com/#README 
- C#程序实现软件开机自动启动的两种常用方法
			C#/WPF/WinForm/.NET程序代码实现软件程序开机自动启动的两种常用方法函数的示例与实例带详细注释 方法一:将软件的快捷方式创建到计算机的自动启动目录下(不需要管理员权限) 1.必要引用 ... 
- [Linux] nginx管理员指南基本功能
			1.运行时控制Nginx进程 NGINX有一个主进程和一个或多个工作进程. 如果启用了缓存,则缓存加载器和缓存管理器进程也会在启动时运行. 主进程的主要目的是读取和评估配置文件,以及维护工作进程. 工 ... 
- JVM运行时数据区内容简述
			JVM运行时数据区分为五个部分:程序计数器.虚拟机栈.本地方法栈.堆.方法区.如下图所示,五部分其中又分为线程共享区域和线程私有区域,下面将分别介绍每一部分. 1. PC程序计数器 程序计数器是一块较 ... 
- MyBatis:事务回滚
			事务的隔离级别:DEFAULT.READ_UNCOMMITED.READ_COMMITTED.REPEATABLE_READ.SERIALIZABLE 事务的传播行为:REQUIRED.SUPPORT ... 
- Java-this
			当方法中的参数和类中变量重名时,使用 this.变量 调用成员变量. public class test1 { String name; int age; public void te(String ... 
- python多任务-线程
			目录 多任务的概念 线程基础 单线程执行 多线程执行 主线程会等待所有子线程结束后才结束 查看线程数量 线程-注意点 线程执行代码的封装 线程的执行顺序 总结 多任务的概念 什么叫"多任务& ... 
- JavaScript事件(含Demo)
			主要事件: onclick 鼠标单击事件 onmouseover 鼠标经过事件 onmouseout 鼠标移开事件 onchange 文本框内容改变事件 onselect 文本框内容被选中事件 onf ... 
- JS实现异步提交
			什么是XMLHttpRequest? XMLHttpRequest对象用于在后台与服务器交换数据 XMLHttpRequst的作用 在不重新加载页面的情况下更新网页 在页面已加载后从服务器请求数据 在 ... 
- 输出映射resultMap
			①:编写接口方法 /** * 根据id查询用户 * @param id * @return */ public User queryUserById3(Integer id); ②:编写映射文件 1: ... 
