PAT 1091. Acute Stroke (30) 3重方向并查集(其实非递归DFS也可以,,)

来源:互联网 发布:知源中学 编辑:程序博客网 时间:2024/05/16 01:37
#include<iostream>#include<cstdio>#include<algorithm>#include<queue>#include<string.h>#include<cmath>#include<string>using namespace std;///*************************题意:给出一个三维立方体,每个点由0或1构成问由1构成的体积共多少且构成的每个体积必须大于t*************************//************************求解要点:用并查集方法:每储存一个1元素,查看其left、up、below 3个相邻的点(由于储存时从上往下,从西往东,从北往南,故一定可以利用之前的信息)若为1,则找到那个点所在集合的父亲(并查集方法)优先让集合们指向left若left不存在则指向up,若up不存在指向below若都不存在,自身为集合。同时注意判断重复指向的情况即up、below、left的父亲可能是同一个集合要加上判断。************************//***********************笔记:1.当让3个集合指向1个时,设定一个优先级先指aa没有则指b,b没有则指c同时进行是否在同一个集合的判断若相同集合,则不进行相加操作。*********************/#define M 1291#define N 132#define K 64#define INF 0xfffffstruct point{int k,i,j;};struct father{struct point nextp;bool flag;int pn;};struct father fa[K][M][N];int a[K][M][N];int n,m,l;struct point getf(int k,int i,int j){point p,pa;p.k=k;p.i=i;p.j=j;if(a[k][i][j]==0){p.k=-1;p.i=-1;p.j=-1;return p;}if(fa[k][i][j].flag==1)return p;pa=fa[k][i][j].nextp;pa=getf(pa.k,pa.i,pa.j);fa[k][i][j].nextp=pa;return pa;}int main(){int t;scanf("%d%d%d%d",&m,&n,&l,&t);memset(a,0,sizeof(a));struct father f,fk,fi,fj,orf;struct point p,pup,pbelow,pleft,pfa;int i,j,k;for(k=0;k<=l+2;k++)for(i=0;i<=m+2;i++)for(j=0;j<=n+2;j++){fa[k][i][j].pn=0;fa[k][i][j].flag=0;}for(k=1;k<=l;k++){for(i=1;i<=m;i++)for(j=1;j<=n;j++){scanf("%d",&a[k][i][j]);//printf("%d %d %d\n",k,i,j);if(a[k][i][j] == 1){p.i=i;p.j=j;p.k=k;fa[k][i][j].pn=1;pbelow=getf(k-1,i,j);pup=getf(k,i-1,j);pleft=getf(k,i,j-1);if(a[k][i][j-1]==1)pfa=pleft;else if(a[k][i-1][j]==1)pfa=pup;else if(a[k-1][i][j]==1)pfa=pbelow;else pfa=p;fa[pfa.k][pfa.i][pfa.j].flag=1;fa[pfa.k][pfa.i][pfa.j].nextp=pfa;//若上一行非0,则加上去,但前提是不与pfa相同//与pfa相同则代表: 可能为left,可能为upif(pup.k!=-1){if(pup.k!=pfa.k || pup.i!=pfa.i || pup.j!=pfa.j){fa[pup.k][pup.i][pup.j].nextp = pfa;fa[pfa.k][pfa.i][pfa.j].pn += fa[pup.k][pup.i][pup.j].pn;fa[pup.k][pup.i][pup.j].flag=0;}}//若上一层非0,则加上去,但前提是不与pfa相同,且不与below相同。//即如果要指向left,而below和up父亲相同,则只需要加一次即可//与pfa相同则代表: 可能为left,可能为up,可能为belowif(pbelow.k!=-1){//注意如果below的父亲和up的父亲相同,说明在同一集合//则below不可加。if(pbelow.k!=pfa.k || pbelow.i!=pfa.i || pbelow.j!=pfa.j){if(pbelow.k!=pup.k || pbelow.i!=pup.i || pbelow.j!=pup.j){fa[pbelow.k][pbelow.i][pbelow.j].nextp = pfa;fa[pfa.k][pfa.i][pfa.j].pn += fa[pbelow.k][pbelow.i][pbelow.j].pn;fa[pbelow.k][pbelow.i][pbelow.j].flag=0;}}}if(k!=pfa.k || i!=pfa.i || j!=pfa.j){fa[k][i][j].nextp = pfa;fa[pfa.k][pfa.i][pfa.j].pn += 1;fa[k][i][j].flag=0;}}}}int ans=0;for(k=1;k<=l;k++)for(i=1;i<=m;i++)for(j=1;j<=n;j++){if(fa[k][i][j].flag==1 && fa[k][i][j].pn >= t){ans+=fa[k][i][j].pn;}}cout<<ans<<endl;return 0;}

原创粉丝点击