如下状态时,可产生最多的能量。
PN
NP
NP
NN
【数据规模】
10% 的数据N≤3;
30% 的数据N≤4;
80% 的数据N≤10;
100% 的数据N≤40。
最小割。
和【BZOJ 2132】 一样的思路。
只是这道题多了一些已知的格子,那么他对应的点与s/t连inf的边,表示他必须属于s集/t集
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> #include <queue> #define M 40*40*40+5 #define inf 0x3f3f3f3f using namespace std; int fx[10][4],c[45][45][45],num[45][45][45],n,tot=1,s,t,h[M],d[M],v[M],cur[M],ans; char S[45][45][45]; struct edge { int from,to,cap,flow,ne; }E[200005]; void Addedge(int from,int to,int cap) { E[++tot]=(edge){from,to,cap,0,h[from]}; h[from]=tot; E[++tot]=(edge){to,from,0,0,h[to]}; h[to]=tot; } bool bfs() { for (int i=s;i<=t;i++) v[i]=0; v[s]=1; d[s]=0; queue<int> q; q.push(s); while (!q.empty()) { int x=q.front(); q.pop(); for (int i=h[x];i;i=E[i].ne) { edge e=E[i]; if (!v[e.to]&&e.cap>e.flow) { v[e.to]=1; d[e.to]=d[x]+1; q.push(e.to); } } } return v[t]; } int dfs(int x,int a) { if (x==t||!a) return a; int flow=0; for (int &i=cur[x];i;i=E[i].ne) { edge &e=E[i]; if (d[e.to]!=d[x]+1) continue; int f=dfs(e.to,min(a,e.cap-e.flow)); if (f) { flow+=f; a-=f; e.flow+=f; E[i^1].flow-=f; if (!a) break; } } return flow; } int dinic() { int flow=0; while (bfs()) { for (int i=s;i<=t;i++) cur[i]=h[i]; flow+=dfs(s,inf); } return flow; } void Paint() { for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) c[0][i][j]=(i+j)&1; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) c[i][j][k]=1^c[i-1][j][k], num[i][j][k]=n*n*(i-1)+n*(j-1)+k; } void Build() { fx[1][1]=fx[3][2]=fx[5][3]=1; fx[2][1]=fx[4][2]=fx[6][3]=-1; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) { int x=num[i][j][k]; if (c[i][j][k]) { if (S[i][j][k]=='P') Addedge(s,x,inf); if (S[i][j][k]=='N') Addedge(x,t,inf); } else { if (S[i][j][k]=='N') Addedge(s,x,inf); if (S[i][j][k]=='P') Addedge(x,t,inf); } for (int p=1;p<=6;p++) { int ni=i+fx[p][1],nj=j+fx[p][2],nk=k+fx[p][3]; if (ni<1||nj<1||nk<1||ni>n||nj>n||nk>n) continue; Addedge(x,num[ni][nj][nk],1); ans++; } } ans>>=1; } int main() { scanf("%d",&n); s=0,t=n*n*n+1; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) scanf("%s",1+S[i][j]); Paint(); Build(); printf("%d\n",ans-dinic()); return 0; }