ENFP-T型人格患者|

_Youngxy

园龄:3年7个月粉丝:5关注:28

[HNOI2013]切糕 解题报告

题目描述

经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B。出于美观考虑,小 A 希望切面能尽量光滑且和谐。于是她找到你,希望你能帮她找出最好的切割方案。 出于简便考虑,我们将切糕视作一个长 P、宽 Q、高 R 的长方体点阵。我们将位于第 z 层中第 x 行、第 y 列上的点称 (x,y,z),它有一个非负的不和谐值 v(x,y,z)。一个合法的切面满足以下两个条件: - 与每个纵轴(一共有 P×Q 个纵轴)有且仅有一个交点。即切面是一个函数 f(x,y),对于所有 (x,y)(x[1,P],y[1,Q]),我们需指定一个切割点 f(x,y),且 1f(x,y)R。 - 切面需要满足一定的光滑性要求,即相邻纵轴上的切割点不能相距太远。对于所有的 1x,xP1y,yQ,若 |xx|+|yy|=1,则 |f(x,y)f(x,y)|D,其中 D 是给定的一个非负整数。 可能有许多切面 f 满足上面的条件,小 A 希望找出总的切割点上的不和谐值最小的那个。

输入输出格式

输入格式

第一行是三个正整数 P,Q,R,表示切糕的长宽高。 第二行有一个非负整数 D,表示光滑性要求。 接下来是 RPQ 列的矩阵,第 z 个矩阵的第 x 行第 y 列是 v(x,y,z)(1xP,1yQ,1zR)

输出格式

仅包含一个整数,表示在合法基础上最小的总不和谐值。

SOLUTION

考虑最小割,通过连INF边强制让相邻的点不割距离超过D的边

如果没有光滑性限制

这个题就是一个ruozhi简单的最小割

在第r层的点x(i,j)与下一层 y 的连(x,y,v[r][i][j])

(因为是每一(i,j)选一个切割点)

这种选择的就可以考虑最小割

那有光滑限制怎么办呢

23031109014111png 699×69 fzoitop

其实就是不能切割相邻的(x,y)(x,y)r距离要小于等于D

那么我们就保证相邻的点的r距离大于D的不会被切割好了

(x,y)(x,y),flow=INF

over!

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+2,INF=1e9,M=1e2+2;
struct node{ll to,val,nxt;}e[N*2];
ll a,n,vis[N],d[N],hd[N],m,ans,cnt,sum,S,T;
const ll dx[]={0,1,0,-1,0},dy[]={1,0,-1,0,0};
bool ok(ll x,ll y){return x>=1&&x<=n&&y>=1&&y<=m;}
void add(ll x,ll y,ll c){
	e[++cnt]={y,c,hd[x]};
	hd[x]=cnt;
}
bool bfs(){
	queue<ll>q;
	memset(d,0,sizeof(d));
	q.push(S);d[S]=1;
	while(!q.empty()){
		ll x=q.front();q.pop();
		for(ll i=hd[x];~i;i=e[i].nxt){
			ll y=e[i].to,w=e[i].val;
			if(w&&!d[y]){
				d[y]=d[x]+1;
				q.push(y);
				if(y==T) return 1; 
			}
		}
	}
	return 0;
}
ll dinic(ll x,ll flow){
	if(x==T) return flow;
	ll r=flow,k;
	for(ll i=hd[x];~i&&r;i=e[i].nxt){
		ll y=e[i].to,w=e[i].val;
		if(w&&d[y]==d[x]+1){
			k=dinic(y,min(r,w));
			if(!k)d[y]=0;
			e[i].val-=k;
			e[i^1].val+=k;
			r-=k;
			if(!r) return flow;
		}
	}
	return flow-r;
}
int main(){
	scanf("%lld%lld",&n,&m);
	cnt=1;
	S=0,T=3*n*m+1;
	memset(hd,-1,sizeof(hd));
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++){
			scanf("%lld",&a);
			sum+=a;
			ll x=(i-1)*m+j;
			add(S,x,a),add(x,S,0);
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++){
			scanf("%lld",&a);
			sum+=a;
			ll x=(i-1)*m+j;
			add(x,T,a),add(T,x,0);
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++){
			scanf("%lld",&a);
			sum+=a;
			ll x=(i-1)*m+j+n*m;
			add(S,x,a),add(x,S,0);
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++){
			scanf("%lld",&a);
			sum+=a;
			ll x=(i-1)*m+j+n*m*2;
			add(x,T,a),add(T,x,0);
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=m;j++){
			ll x=(i-1)*m+j;
			for(ll k=0;k<=4;k++){
				ll xi=i+dx[k],yj=j+dy[k];
				if(!ok(xi,yj))continue;
				ll y=(xi-1)*m+yj;
				add(x+n*m,y,INF),add(y,x+n*m,0);
				add(y,x+n*m*2,INF),add(x+n*m*2,y,0);
			}
		}
	}
	while(bfs()){
		ans+=dinic(S,INF);
	}
	printf("%lld",sum-ans);
	return 0;
}

完结撒花❀

★,°:.☆( ̄▽ ̄)/$:.°★

本文作者:Yvette的博客

本文链接:https://www.cnblogs.com/yvette1217/p/17206100.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Youngxy  阅读(26)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示