3144: [Hnoi2013]切糕
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1261 Solved: 700
[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
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
Solution
把一个立体几何的东西换成平面几何,想成一个矩阵
每个矩阵有一些值要取,而且要满足相邻的相差不到D
所以考虑分层建图,按高度分层,然后最小割即可
感觉是个比较经典的模型?
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 50*50*50 #define maxm 1000100 int p,q,r,d,ans; int val[50][50][50]; struct Edgenode{int to,next,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) {cnt++;edge[cnt].to=v;edge[cnt].cap=w;edge[cnt].next=head[u];head[u]=cnt;} void insert(int u,int v,int w) {add(u,v,w);add(v,u,0);} // int dis[maxn],que[maxn<<1],cur[maxn],S,T; bool bfs() { for (int i=S; i<=T; i++) dis[i]=-1; que[0]=S; dis[S]=0; int he=0,ta=1; while (he<ta) { int now=que[he++]; for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,que[ta++]=edge[i].to; } return dis[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int w,used=0; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[loc]+1) { w=dfs(edge[i].to,min(low-used,edge[i].cap)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (edge[i].cap) cur[loc]=i; if (used==low) return low; } if (!used) dis[loc]=-1; return used; } #define inf 0x7fffffff int dinic() { int tmp=0; while (bfs()) { for (int i=S; i<=T; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; }// int loc(int x,int y,int z) {if (z==0) return 0;return (z-1)*p*q+(x-1)*q+y;} void make() { S=0,T=p*q*r+1; for (int i=1; i<=p; i++) for (int j=1; j<=q; j++) { for (int k=1; k<=r; k++) { insert(loc(i,j,k-1),loc(i,j,k),val[i][j][k]); if(k>d) { if (i-1>=1) insert(loc(i,j,k),loc(i-1,j,k-d),inf); if (i+1<=p) insert(loc(i,j,k),loc(i+1,j,k-d),inf); if (j-1>=1) insert(loc(i,j,k),loc(i,j-1,k-d),inf); if (j+1<=q) insert(loc(i,j,k),loc(i,j+1,k-d),inf); } } insert(loc(i,j,r),T,inf); } } int main() { p=read(),q=read(),r=read(); d=read(); for (int i=1; i<=r; i++) for (int j=1; j<=p; j++) for (int k=1; k<=q; k++) val[j][k][i]=read(); make(); ans=dinic(); printf("%d ",ans); return 0; }
吐槽自己代码丑,我认了....
话说数学和语文学的真不好....刚看题居然没看懂......