3144: [Hnoi2013]切糕

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1495  Solved: 819
[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,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,求最小代价...

考虑如果没有距离限制怎么建图...把每个格子拆成r个点,串成一条链和ST相连,求最小割就是答案...

现在有了距离限制...怎么办??最常用的限制方法就是添加容量为+∞的边...

我们把(i,j,k)向(i',j',k-d)(相邻的格子)连边...这个正确性画一下图YY一下就好...

代码:

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
#define inf 0x3f3f3f3f
using namespace std; const int maxn=+,maxm=+; int n,m,h,d,S,T,cnt,hd[maxn],fl[maxm],to[maxm],nxt[maxm],pos[maxn]; int mv[][]={,,,-,,,-,}; inline bool bfs(void){
memset(pos,-,sizeof(pos));
int head=,tail=,q[maxn];
q[]=S,pos[S]=;
while(head<=tail){
int top=q[head++];
for(int i=hd[top];i!=-;i=nxt[i])
if(pos[to[i]]==-&&fl[i])
pos[to[i]]=pos[top]+,q[++tail]=to[i];
}
return pos[T]!=-;
} inline int find(int v,int f){
if(v==T)
return f;
int res=,t;
for(int i=hd[v];i!=-&&f>res;i=nxt[i])
if(pos[to[i]]==pos[v]+&&fl[i])
t=find(to[i],min(fl[i],f-res)),res+=t,fl[i]-=t,fl[i^]+=t;
if(!res)
pos[v]=-;
return res;
} inline int dinic(void){
int res=,t;
while(bfs())
while(t=find(S,inf))
res+=t;
return res;
} inline void add(int s,int x,int y){
fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
fl[cnt]=;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++;
} signed main(void){
// freopen("in.txt","r",stdin);
memset(hd,-,sizeof(hd));
scanf("%d%d%d%d",&n,&m,&h,&d);
S=,T=n*m*h+;
for(int k=,x;k<=h;k++)
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
scanf("%d",&x);
if(k==)
add(x,S,((i-)*m+j-)*h+k);
else
add(x,((i-)*m+j-)*h+k-,((i-)*m+j-)*h+k);
if(k==h)
add(inf,((i-)*m+j-)*h+k,T);
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
for(int k=d+;k<=h;k++)
for(int t=;t<;t++){
int x=i+mv[t][],y=j+mv[t][];
if(x>=&&x<=n&&y>=&&y<=m)
add(inf,((i-)*m+j-)*h+k,((x-)*m+y-)*h+k-d);
}
printf("%d\n",dinic());
return ;
}//Cap ou pas cap. Cap.

By NeighThorn

最新文章

  1. MD测试
  2. PHP开发模式之代理技术
  3. log4j2配置
  4. 【数位统计】之【spoj1433 KPSUM】
  5. SharePoint 2013 配置我的网站 图文引导
  6. Sqli-labs less 34
  7. 《云大课程助手》Android刷课工具来袭
  8. mysql 存储过程的应用
  9. Team Foundation Server 2015使用教程--团队项目创建
  10. WeMall微商城源码报名插件Apply的主要源码
  11. .elf格式内容
  12. [LeetCode] K Empty Slots K个空槽
  13. 【Python3爬虫】最新的模拟登录新浪微博教程
  14. Android的WebView调试工具(无需Fan墙,可同时调试多个设备,永不过期)
  15. leedcode算法解题思路
  16. java集合的实现细节--ArrayList和LinkedList
  17. ICS 组件 for lazarus 1.0.12
  18. java基础基础总结----- Date
  19. Android 本地播放器
  20. tensorflow reduction_indices理解

热门文章

  1. Lisp和SICP
  2. JSON(及其在ajax前后端交互的过程)小识
  3. # ios开发 @property 和 Ivar 的区别
  4. 剖析并利用Visual Studio Code在Mac上编译、调试c#程序
  5. iOS: 为画板App增加 Undo/Redo(撤销/重做)操作
  6. [原创]django+ldap实现统一认证部分一(django-auth-ldap实践)
  7. Windows下Memcached安装与配置实例
  8. 前端开发css实战:使用css制作网页中的多级菜单
  9. c#面向对象基础技能——学习笔记(三)基于OOP思想研究对象的【方法】
  10. 【译】Asp.net mvc 使用ITextSharp PDF to HTML (解决img标签问题)