总结一下这一题我的思考过程,以及与题解的对比。
这题我首先考虑二维平面的切法,发现就是一个最短路,然后套在三维的情况,发现无法保证每个(x,y)都经过。所以说这种思路是不对的。一开始就不对,后面怎么可能对。一般靠谱的思路自己都会觉得靠谱,我那样搞十分玄学肯定不是正解。
最小费用好像很玄学,考虑最小割吧,既然一个(x,y)只要选一个,我们把同一纵行串成一链,那么求每条链的最小割就行了。这样看起来挺靠谱的,于是就有了继续思考的勇气。
考虑限制条件怎么转化成网络流模型。
选了x在旁边的就只能选
经过一些尝试性的探索可以发现x向四个柱子的
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
#include<climits>
#define X first
#define Y second
#define DB double
#define lc now<<1
#define rc now<<1|1
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define pdd pair<DB,DB>
#define ull unsigned LL
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
template<typename T>void Read(T& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
const int MAXN=40*40*40+10;
int p,q,r,id[45][45][45],w[45][45][45],tot=0,d;
struct Edge{
int u,v,cap,flow;
Edge(int u,int v,int cap,int flow):u(u),v(v),cap(cap),flow(flow){}
};
struct Dinic{
int cur[MAXN],dis[MAXN],vis[MAXN],S,T;
vector<int> G[MAXN];
vector<Edge> edges;
void add(int u,int v,int c)
{
edges.pb(Edge(u,v,c,0));
edges.pb(Edge(v,u,0,0));
int m=edges.size();
G[u].pb(m-2);
G[v].pb(m-1);
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(S);
dis[S]=1;
vis[S]=1;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++)
{
Edge& e=edges[G[u][i]];
if(!vis[e.v]&&e.cap-e.flow)
{
dis[e.v]=dis[u]+1;
vis[e.v]=1;
q.push(e.v);
}
}
}
return vis[T];
}
int DFS(int x,int a)
{
if(x==T||a==0)return a;
int f=0,flow=0;
for(int& i=cur[x];i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(dis[e.v]==dis[x]+1&&(f=(DFS(e.v,min(a,e.cap-e.flow)))>0))
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
a-=f;
flow+=f;
if(a==0)break;
}
}
return flow;
}
int maxflow()
{
int mx=0;
while(BFS())
{
memset(cur,0,sizeof(cur));
mx+=DFS(S,INF);
}
return mx;
}
}Graph;
int main()
{
#ifndef ONLINE_JUDGE
freopen("cake.in","r",stdin);
freopen("cake.out","w",stdout);
#endif
Read(p),Read(q),Read(r),Read(d);
for(int i=1;i<=r;i++)
for(int j=1;j<=p;j++)
for(int k=1;k<=q;k++)
Read(w[i][j][k]),id[i][j][k]=++tot;
Graph.S=++tot,Graph.T=++tot;
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++)
{
for(int k=r;k>=1;k--)
{
if(k==r)
Graph.add(Graph.S,id[k][i][j],w[k][i][j]);
else
Graph.add(id[k+1][i][j],id[k][i][j],w[k][i][j]);
if(k+d<=r)
{
if(i>1)
Graph.add(id[k][i][j],id[k+d][i-1][j],INF);
if(i<p)
Graph.add(id[k][i][j],id[k+d][i+1][j],INF);
if(j>1)
Graph.add(id[k][i][j],id[k+d][i][j-1],INF);
if(j<q)
Graph.add(id[k][i][j],id[k+d][i][j+1],INF);
}
if(k==1)
Graph.add(id[k][i][j],Graph.T,INF);
}
}
cout<<Graph.maxflow()<<endl;
}