
F.A.Qs | Home | Discuss | ProblemSet | Status | Ranklist | Contest | 入门OJ | Login | Register | 捐赠本站 |
---|
Notice:为保证OJ试题质量,今后添加的试题如有发现出现重复,请联系我们删除,谢谢!
Problem 3144. – [Hnoi2013]切糕
3144: [Hnoi2013]切糕
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2021 Solved: 1090
[ 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
思路:最大流,每个点向其上一层连一条容量为一的边;然后考虑限制;
每个点i向[i-D]连一条inf的边,这样保证如果选择了[i-D]以下的边,那么会导致该条道路还可以增广,所以满足了限制条件。注意输入P,Q,R的顺序。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 1e9
#define MAXN 300005
using namespace std;
queue<int> q;
struct node
{
int from,to,remain,next;
}e[MAXN*10];
int e_num=-1,point[MAXN];
int deep[MAXN],cur[MAXN];
bool vis[MAXN];
int s,t,ans,n,m;
int P,R,Q,D;
inline int get()
{
int x=0,p=1;char c;
c=getchar();
while (c<'0'||c>'9') {if (c=='-') p=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*p;
}
inline void add(int from,int to,int remain)
{
++e_num;
e[e_num].from=from;
e[e_num].to=to;
e[e_num].remain=remain;
e[e_num].next=point[from];
point[from]=e_num;
}
bool bfs(int from,int to)
{
memset(deep,0x7f,sizeof(deep));
memset(vis,0,sizeof(vis));
for (int i=0;i<=t;i++)
cur[i]=point[i];
deep[from]=0;
vis[from]=1;
q.push(from);
while (!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for (int i=point[u];i!=-1;i=e[i].next)
if (deep[e[i].to]>inf&&e[i].remain)
{
deep[e[i].to]=deep[u]+1;
if (!vis[e[i].to])
{
q.push(e[i].to);
vis[e[i].to]=true;
}
}
}
return deep[to]<inf;
}
int dfs(int from,int to,int limit)
{
int f,flow=0;
if (!limit) return 0;
if (from==to) return limit;
for (int i=cur[from];i!=-1;i=e[i].next)
{
cur[from]=i;
if (deep[e[i].to]==deep[from]+1&&(f=dfs(e[i].to,to,min(limit,e[i].remain))))
{
flow+=f;
limit-=f;
e[i].remain-=f;
e[i^1].remain+=f;
if (!limit) break;
}
}
return flow;
}
void dinic()
{
while (bfs(s,t))
ans+=dfs(s,t,inf);
}
void addedge(int x,int y,int z)
{
add(x,y,z);
add(y,x,0);
}
int calc(int x,int y,int z)
{
return (x-1)*P*Q+(y-1)*Q+z;
}
int main()
{
freopen("nutcake.in","r",stdin);
freopen("nutcake.out","w",stdout);
int x,cnt=0;
memset(point,-1,sizeof(point));
P=get();Q=get();R=get();D=get();
s=0;t=(P+1)*(Q+1)*(R+1)+100;
for (int i=1;i<=R;i++)
for (int j=1;j<=P;j++)
{
for (int k=1;k<=Q;k++)
{
if (i==1) addedge(s,calc(1,j,k),inf);
if (i==R) addedge(calc(R+1,j,k),t,inf);
x=get();
addedge(calc(i,j,k),calc(i+1,j,k),x);
}
}
for (int i=D+1;i<=R;i++)
for (int j=1;j<=P;j++)
for (int k=1;k<=Q;k++)
{
if (j+1<=P)
addedge(calc(i,j,k),calc(i-D,j+1,k),inf);
// printf("%d %d---%d %d\n",j,k,j+1,k);
if (j-1>=1)
addedge(calc(i,j,k),calc(i-D,j-1,k),inf);
if (k+1<=Q)
addedge(calc(i,j,k),calc(i-D,j,k+1),inf);
// printf("%d %d---%d %d\n",j,k,j,k+1);
if (k-1>=1)
addedge(calc(i,j,k),calc(i-D,j,k-1),inf);
}
dinic();
printf("%d",ans);
}