洛谷 P3227 BZOJ 3144 [HNOI2013]切糕

2023-12-13 16:59

本文主要是介绍洛谷 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)。一个合法的切面满足以下两个条件:

  1. 与每个纵轴(一共有 P*Q 个纵轴)有且仅有一个交点。即切面是一个函数 f(x,y),对于所有 1≤x≤P, 1≤y≤Q,我们需指定一个切割点 f(x,y),且 1≤f(x,y)≤R。

  2. 切面需要满足一定的光滑性要求,即相邻纵轴上的切割点不能相距太远。对于所有的 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

 

吐槽

  我为什么最近会突然开始刷网络流呢?因为最近在长乐一中集训,难得美国队长妹滋滋大佬来讲课,讲了一整天的网络流,我记了差不多20页信笺纸的笔记……(听课时开着电脑会损失很大的,不骗你,记笔记是个很好的学习习惯啊) 那天听得我脑力耗尽,去吃中午饭时让同行的Neil描述成——让他想到了一个游戏“饥荒”。详见……

  最近请教某些大佬时遭到了BS,RP暴涨啊,常数巨小,下面的代码占领了洛谷的rank1~3(我交了三次嘻嘻),不开O2时正好rank20(交那三次之前)。

  真记不得这个题面玩的梗是咋回事了……好像那是我初二上学期的时候,那段时间嫦娥几号来着还着陆在月球来着,我那晚看了CCTV三个小时的直播。记得那时日子多么美好…………

  好了,暂停回忆吧,咳咳!开始讲题——

解题思路

   一道离散变量模型裸题。妹滋滋的幻灯片上这么说的——//不知道这样是否违反了某些基本法,如果有请告知,我删除

  对于切糕这题——

源代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>int p,q,r,D;
int cake[42][42][42]={0};int s,t;
struct Edge{int next,to,c;
}e[200010];
int head[200010],cnt=2;
void add(int u,int v,int c)
{e[cnt]={head[u],v,c};head[u]=cnt++;e[cnt]={head[v],u,0};head[v]=cnt++;
}int dis[200010]={0};
bool bfs()
{memset(dis,0,sizeof(dis));dis[s]=1;std::queue<int> q;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(e[i].c==0||dis[v]) continue;dis[v]=dis[u]+1;q.push(v);}}return dis[t]!=0;
}int dfs(int u,int flow)
{if(flow==0||u==t) return flow;int flow_sum=0;for(int i=head[u];i;i=e[i].next){int v=e[i].to,f=std::min(e[i].c,flow-flow_sum);if(dis[v]!=dis[u]+1||!e[i].c) continue;int temp=dfs(v,f);e[i].c-=temp;e[i^1].c+=temp;flow_sum+=temp;if(flow<=flow_sum) break;}if(flow_sum==0) dis[u]=-1;return flow_sum;
}int dinic()
{int ans=0;while(bfs())while(int temp=dfs(s,0x7f7f7f7f))ans+=temp;return ans;
}inline int id(int x,int y,int z)
{if(z==0) return s;if(z==r+1) return t;return (z-1)*p*q+(x-1)*q+y;
}int main()
{//freopen("test.in","r",stdin);scanf("%d%d%d%d",&p,&q,&r,&D);s=p*q*r+1,t=s+1;for(int i=1;i<=r;i++)for(int j=1;j<=p;j++)for(int k=1;k<=q;k++)scanf("%d",&cake[j][k][i]);//网络流的题输入都很恶心,优化高维数组取值太饶了,索性不搞
    ;/***建图***/int bh[4][2]={{0,1},{0,-1},{-1,0},{1,0}};for(int i=1;i<=p;i++){for(int j=1;j<=q;j++){for(int k=1;k<=r;k++){add(id(i,j,k-1),id(i,j,k),cake[i][j][k]);if(k>D)//四周
                {int h=k-D;for(int aa=0;aa<4;aa++){int ii=i+bh[aa][0],jj=j+bh[aa][1];if(ii>0&&ii<=p&&jj>0&&jj<=q)add(id(i,j,k),id(ii,jj,h),0x7f7f7f7f);}}}add(id(i,j,r),t,0x7f7f7f7f);}}printf("%d",dinic());return 0;
}

 

这篇关于洛谷 P3227 BZOJ 3144 [HNOI2013]切糕的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/489215

相关文章

高精度计算(代码加解析,洛谷p1601,p1303)除法待更新

目录 高精度加法 高精度减法 高精度乘法 高精度加法 我们知道在c++语言中任何数据类型都有一定的表示范围。当两个被加数很大时,正常加法不能得到精确解。在小学,我们做加法都采用竖式方法。那么我们也只需要按照加法进位的方式就能得到最终解。 8 5 6+ 2 5 5-------1 1 1 1 加法进位: c[i] = a[i] + b[i];if(c[i] >=

洛谷 凸多边形划分

T282062 凸多边形的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 先整一个半成品,高精度过两天复习一下补上 #include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#include <vector>#include <map>

能量项链,洛谷

解释:  环形dp问题还是考虑将环拉直,可以参考我上一篇文章:环形石子合并 [2 3 5 10 2] 3 5 10 将环拉直,[]内是一个有效的区间,可以模拟吸收珠子的过程,         如[2 3 5] <=>(2,3)(3,5)    2是头,3是中间,5是尾 len >= 3:因为最后[2 10 2]是最小的可以合并的有效区间 len <= n + 1因为[2 3

洛谷P5490扫描线

0是最小的数字,将一个线段看成一个区间,对于一个矩形,从下扫到上,入边为1,而出边为-1,意思是将这个区间上的所有点加1(区间修改).把线段表示为Line[i],其中记录了l,r,h,tag,左右端点,高度,入边还是出边(1或-1) 那么每次区间修改后不为0的区间它的值可能是1,2,3或者是其它数字,这不好统计,可以将它转化一下,0是不是表示没有被覆盖过的地方,我们只要统计0的个数然后用总长减去

【BZOJ】1324 Exca王者之剑 最大权独立集

传送门:【BZOJ】1324  Exca王者之剑 题目分析:赤裸裸的最大权独立集。。。最小割解决 代码如下: #include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int

【BZOJ】1026: [SCOI2009]windy数 数位DP

传送门:【BZOJ】1026: [SCOI2009]windy数 题目分析:数位DP水题。 代码如下: #include <stdio.h>#include <cstring>#include <algorithm>#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )#define For( i ,

【BZOJ】2152: 聪聪可可 点分治

传送门:【BZOJ】2152: 聪聪可可 题目分析:记录权值和%3的路径的个数。。。然后去重。。没了。。 代码如下: #include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std ;typedef lo

挤牛奶洛谷uasco

题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒。第二个农民在700秒开始,在 1200秒结束。第三个农民在1500秒开始2100秒结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒)。

洛谷刷题(7)

P8738 [蓝桥杯 2020 国 C] 天干地支 题目描述 古代中国使用天干地支来记录当前的年份。 天干一共有十个,分别为:甲(jiǎ)、乙(yǐ)、丙(bǐng)、丁(dīng)、戊 (wù)、己(jǐ)、庚(gēng)、辛(xīn)、壬(rén)、癸(guǐ)。 地支一共有十二个,分别为:子(zǐ)、丑(chǒu)、寅(yín)、卯(mǎo)、辰(chén)、巳(sì)、午(wǔ)、

C++ 洛谷 哈希表(对应题库:哈希,hash)习题集及代码

马上就开学了,又一个卷季,不写点东西怎么行呢?辣么,我不准备写那些dalao们都懂得,熟练的,想来想去,最终还是写哈希表吧!提供讲解&题目&代码解析哦! 奉上题目链接: 洛谷题目 - 哈希,hash 1、哈希、哈希表(hash)简介 哈希(Hash)是一种将任意长度的输入映射为固定长度输出的算法。哈希函数的输出值称为哈希值或散列值。哈希函数具有以下特性: 确定性:对于相同的输入