bzoj 3144: [Hnoi2013]切糕

Description

Input

第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。 
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。

Output

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

Sample Input

2 2 2

1

6 1

6 1

2 6

2 6

Sample Output

6

HINT

最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1

Source

论学好语文的重要性,真的看不懂这个题目在说什么,这个人的切法真的是清新脱俗。。。

先把题目翻译一下:

有一个p*q的矩阵,每个位置上的格子上可以选r个数字中的一个填,每选一个数字都会有一个费用,并且相邻的格子上的数字相差不超过d,

求把每个格子填完数后的最小费用;

首先不考虑相差不超过d的限制,是一个经典的最小割模型:

每个点有n种选择,用s->x1->x2->x3->x4->T,如果割掉x1->x2的边,表示选择了x2,把图画出来的话很容易懂

然后考虑d的限制,用的是Inf限制不合法决策的方法(是最小割中常用技巧)

对于每个点加入选了k,那么该点的k向周围的点的k-d连Inf,周围点的k+d+1向该点的k+1连Inf的边,

把图画出来之后判断要如何割边才能使S-->T连通,可以把不合法的割边中增加Inf的流量从而使该决策不会被选为最小割中;

玄学剪枝真重要

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#define RG register
using namespace std;
typedef long long ll;
const int N=300050;
const int Inf=19260817;
int gi(){
  int x=0,flag=1;
  char ch=getchar();
  while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) flag=-1;ch=getchar();}
  while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
  return x*flag;
}
int id[50][50][50],f[50][50][50],p,q,r,d,tt,S,T;
int mx[5]={1,-1,0,0},my[5]={0,0,1,-1};
int head[N],to[N],nxt[N],level[N],s[N],cnt=1,F,Q[N*5];
void Addedge(int x,int y,int z) {
  to[++cnt]=y,s[cnt]=z,nxt[cnt]=head[x],head[x]=cnt;
}
void lnk(int x,int y,int z){
  Addedge(x,y,z),Addedge(y,x,0);
}
inline bool bfs(){
  for(RG int i=S;i<=T;i++) level[i]=0;
  Q[0]=S,level[S]=1;int t=0,sum=1;
  while(t<sum){
    int x=Q[t++];
    if(x==T) return 1;
    for(RG int i=head[x];i;i=nxt[i]){
      int y=to[i];
      if(s[i]&&level[y]==0){
	level[y]=level[x]+1;
	Q[sum++]=y;
      }
    }
  }
  return 0;
}
inline int dfs(RG int x,int maxf){
  if(x==T) return maxf;
  int ret=0;
  for(RG int i=head[x];i;i=nxt[i]){
    int y=to[i],f=s[i];
    if(level[y]==level[x]+1&&f){
      int minn=min(f,maxf-ret);
      f=dfs(y,minn);
      s[i]-=f,s[i^1]+=f,ret+=f;
      if(ret==maxf) break;
    }
  }
  if(!ret) level[x]=0;
  return ret;
}
void Dinic(){
  while(bfs()) F+=dfs(S,Inf);
}
int main(){
  freopen("cake.in","r",stdin);
  freopen("cake.out","w",stdout);
  p=gi(),q=gi(),r=gi(),d=gi();
  for(int i=1;i<=r;i++)
    for(int j=1;j<=p;j++)
      for(int k=1;k<=q;k++){
	f[j][k][i]=gi(),id[j][k][i]=++tt;
      }
  S=0,T=++tt;
  for(int i=1;i<=p;i++)
    for(int j=1;j<=q;j++){
      lnk(S,id[i][j][1],f[i][j][1]);
      for(int k=1;k<r;k++) lnk(id[i][j][k],id[i][j][k+1],f[i][j][k+1]);
      lnk(id[i][j][r],T,Inf);
      for(int k=0;k<4;k++){
	int x=i+mx[k],y=j+my[k];
	if(1<=x&&x<=p&&1<=y&&y<=q){
	  for(int z=1;z<=r;z++){
	    int zz=z-d,zzz=z+d+1;
	    if(1<=zz&&zz<=r) lnk(id[i][j][z],id[x][y][zz],Inf);
	    if(1<=zzz&&zzz<=r) lnk(id[x][y][zzz],id[i][j][z+1],Inf);
	  }
	}
      }
    }
  Dinic();printf("%d\n",F);
  return 0;
}
时间: 2024-10-10 15:37:36

bzoj 3144: [Hnoi2013]切糕的相关文章

bzoj 3144: [Hnoi2013]切糕 最小割

3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 681  Solved: 375[Submit][Status] Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40,0≤D≤

[BZOJ 3144] [Hnoi2013] 切糕 【最小割】

题目链接:BZOJ - 3144 题目分析 题意:在 P * Q 的方格上填数字,可以填 [1, R] . 在 (x, y) 上填 z 会有 V[x][y][z] 的代价.限制:相邻两个格子填的数字的差的绝对值不能超过 D . 求一个合法的最小总代价. 这道题是一个最小割模型,直接说建图吧. 建图:每个点 (x, y) 拆成 R 个点,(x, y, z) 代表 (x, y) 填 z. 然后从 S 向 (*, *, 1) 连 INF ,从 (*, *, R) 向 T 连 INF . 然后对于 (i

洛谷 P3227 BZOJ 3144 [HNOI2013]切糕

题目描述 经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B.出于美观考虑,小 A 希望切面能尽量光滑且和谐.于是她找到你,希望你能帮她找出最好的切割方案. 出于简便考虑,我们将切糕视作一个长 P.宽 Q.高 R 的长方体点阵.我们将位于第 z层中第 x 行.第 y 列上(1≤x≤P, 1≤y≤Q, 1≤z≤R)的点称为(x,y,z),它有一个非负的不和谐值 v(x,y,z).一个合法的切面满足以下两个条件: 与每个纵轴(一共有 P*Q 个纵轴)有且

【BZOJ 3144】 3144: [Hnoi2013]切糕 (最小割模型)

3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1764  Solved: 965 Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超

3144: [Hnoi2013]切糕

3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1526  Solved: 827[Submit][Status][Discuss] Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q

【BZOJ】3144: [Hnoi2013]切糕

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3144 MDZZ,不知道为什么被卡常数了/TAT(特判才过去的....论vector的危害性? 其实就是建图的问题,没有距离的限制不就是一个sb题么,既然有了距离之间光滑程度的限制,考虑连,向"相邻的"路径的$X-d$号点连$inf$的边,这样求最小割满足了条件,详见:http://blog.csdn.net/thy_asdf/article/details/50428973 1

bzoj千题计划142:bzoj3144: [Hnoi2013]切糕

http://www.lydsy.com/JudgeOnline/problem.php?id=3144 如果D=2 ,两个点,高度为4,建图如下 #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 64005 #define M 323205 const i

【bzoj3144】[Hnoi2013]切糕 最小割

[Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2228  Solved: 1220[Submit][Status][Discuss] Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40

【BZOJ 3144】 [Hnoi2013]切糕 真&#183;最小割

一开始一脸懵逼后来发现,他不就是割吗,我们只要满足条件就割就行了,于是我们把他连了P*Q*R条边,然而我们要怎样限制D呢?我们只要满足对于任意相邻的两条路,只要其有个口大于D就不行就好了因此我们只要把每个点向离他D距离的下面的店连一条Inf连线就可以啦,因此我们就满足了一定是所有相邻的路径上存在不超过距离D的缺口,由于满足这条性质因此至少存在一层两两之间距离不超过D的膜因此最终答案一定是每条路上割一个,因此就让他跑去把! #include <cstdio> #include <cstri