P3227 [HNOI2013]切糕
时间:2022-05-08
本文章向大家介绍P3227 [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 个纵轴)有且仅有一个交点。即切面是一个函数 f(x,y),对于所有 1≤x≤P, 1≤y≤Q,我们需指定一个切割点 f(x,y),且 1≤f(x,y)≤R。
- 切面需要满足一定的光滑性要求,即相邻纵轴上的切割点不能相距太远。对于所有的 1≤x,x’≤P 和 1≤y,y’≤Q,若|x-x’|+|y-y’|=1,则|f(x,y)-f(x’,y’)| ≤D,其中 D 是给定的一个非负整数。 可能有许多切面f 满足上面的条件,小A 希望找出总的切割点上的不和谐值最小的那个。
输入输出格式
输入格式:
第一行是三个正整数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。
输出格式:
仅包含一个整数,表示在合法基础上最小的总不和谐值。
输入输出样例
输入样例#1:
2 2 2
1
6 1
6 1
2 6
2 6
输出样例#1:
6
说明
最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1
我们将点转化成边,那么选点就等于割边,第一个条件满足
对于第二个条件我们可以用一些inf的边来"屏蔽"那些不能割的边,从z向"相邻的"路径的z-d号点连inf的边(如上图)这样做之后,如果删了这条边,我们还可以通过这些桥梁,从相邻的路径的一段[z-d,z+d]绕过,所以割那些边就没有意义了
从而实现必须割[z-d,z+d]的目的
来源:洛谷题解
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<queue>
6 using namespace std;
7 const int MAXN=200001;
8 const int INF = 1e8;
9 inline void read(int &n)
10 {
11 char c='+';int x=0;bool flag=0;
12 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
13 while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
14 n=flag==1?-x:x;
15 }
16 int n,m,s,t;
17 struct node
18 {
19 int u,v,flow,nxt;
20 }edge[MAXN];
21 int head[MAXN];
22 int cur[MAXN];
23 int num=0;
24 int deep[MAXN];
25 int tot=0;
26 void add_edge(int x,int y,int z)
27 {
28 edge[num].u=x;
29 edge[num].v=y;
30 edge[num].flow=z;
31 edge[num].nxt=head[x];
32 head[x]=num++;
33 }
34 void add(int x,int y,int z)
35 {
36 add_edge(x,y,z);
37 add_edge(y,x,0);
38 }
39 bool BFS()
40 {
41 memset(deep,0,sizeof(deep));
42 deep[s]=1;
43 queue<int>q;
44 q.push(s);
45 while(q.size()!=0)
46 {
47 int p=q.front();
48 q.pop();
49 for(int i=head[p];i!=-1;i=edge[i].nxt)
50 if(!deep[edge[i].v]&&edge[i].flow)
51 deep[edge[i].v]=deep[edge[i].u]+1,
52 q.push(edge[i].v);
53 }
54 return deep[t];
55
56 }
57 int DFS(int now,int nowflow)
58 {
59 if(now==t||nowflow<=0)
60 return nowflow;
61 int totflow=0;
62 for(int &i=cur[now];i!=-1;i=edge[i].nxt)
63 {
64 if(deep[edge[i].v]==deep[edge[i].u]+1&&edge[i].flow)
65 {
66 int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
67 edge[i].flow-=canflow;
68 edge[i^1].flow+=canflow;
69 totflow+=canflow;
70 nowflow-=canflow;
71 if(nowflow<=0)
72 break;
73 }
74
75 }
76 return totflow;
77 }
78 void Dinic()
79 {
80 int ans=0;
81 while(BFS())
82 {
83 memcpy(cur,head,MAXN);
84 ans+=DFS(s,1e8);
85 }
86 printf("%d",ans);
87 }
88 int a[41][41][41];
89 int cnt=0;
90 int xx[5]={-1,+1,0,0};
91 int yy[5]={0,0,-1,+1};
92 int main()
93 {
94 memset(head,-1,sizeof(head));
95 int P,Q,R,D;
96 read(P);read(Q);read(R);read(D);
97 for(int i=1;i<=R+1;i++)
98 for(int j=1;j<=P;j++)
99 for(int k=1;k<=Q;k++)
100 a[i][j][k]=++cnt;
101 s=0;t=cnt+1;
102 for(int i=1;i<=P;i++)
103 for(int j=1;j<=Q;j++)
104 {
105 add(s,a[1][i][j],INF);
106 add(a[R+1][i][j],t,INF);//上下界
107 }
108 for(int i=1;i<=R;i++)
109 for(int j=1;j<=P;j++)
110 for(int k=1;k<=Q;k++)
111 {
112 int p;read(p);
113 add(a[i][j][k],a[i+1][j][k],p);
114 }// 连边
115 for(int i=D+1;i<=R;i++)
116 for(int j=1;j<=P;j++)
117 for(int k=1;k<=Q;k++)
118 for(int m=0;m<4;m++)
119 if(a[i-D][j+xx[m]][k+yy[m]]>0)
120 add(a[i][j][k],a[i-D][j+xx[m]][k+yy[m]],INF);
121 //for(int i=1;i<=num-1;i++)
122 //printf("%d %d %dn",edge[i].u,edge[i].v,edge[i].flow);
123 Dinic();
124 return 0;
125 }
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- WebAssembly之emcc编译命令
- 食堂店小二儿教你学会栈
- Istio流量管理实现机制深度解析-基于1.4.0更新
- Istio 运维实战系列(1):应用容器对 Envoy Sidecar 的启动依赖问题
- R语言基于Reactome数据库的富集分析
- WiredTiger存储引擎之五:与事务相关的数据结构以及并发控制机制
- Tomcat NIO(8)-Poller线程的阻塞与唤醒
- 你的第一个React App (一 ) - 项目初始化
- 被JDK坑的没商量?来试试这些方法吧
- k8s 代码走读---client-go 编程交互测试代码
- C#网络类智能开关控制板实例
- Flume拦截器实现按照事件时间接入HDFS
- Day4.Linux用户权限
- 如何使用Canal同步MySQL的Binlog到Kafka
- Go 每日一库之 gabs