题目链接:
http://poj.org/problem?id=1063
题目大意:
给n*m*k的长方体,每个单位体积的正方体按先n,再m,最后k的顺序编号,也即(0~n*m*k-1)。对给定的号码正方体,求最后裸漏在外面的正方体面数。
解题思路:
注意两种情况:1、当外面正方体全部包含内部时,内部空心部分的面不能计算。
2、当出现凹形时,内面有多个。
这道题在poj上提交很容易过,在zoj上一直Segmentation Fault.不知道什么原因,哪位大神知道的话,恳请指导哈。
分析:先对每一个面层从外往内dfs,标记外部的连通块,然后对每个正方体判断六个面相邻的正方体是否是外部连通块或者是出界的情况。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define Maxn 65
struct Point
{
int x,y,z;
}pp[Maxn*Maxn*Maxn];
int n,m,k,sum;
int dir[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};
bool out[Maxn][Maxn][Maxn];
bool give[Maxn][Maxn][Maxn];
bool iscan(int x,int y,int z)
{
if(x<0||x>=n||y<0||y>=m||z<0||z>=k)
return false;
return true;
}
void dfs(int x,int y,int z)
{
if(give[x][y][z]||out[x][y][z])
return ;
out[x][y][z]=true;
for(int i=0;i<6;i++)
{
int xx=x+dir[i][0],yy=y+dir[i][1],zz=z+dir[i][2];
if(!iscan(xx,yy,zz))
continue;
if(out[xx][yy][zz])
continue;
dfs(xx,yy,zz);
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d%d%d%d",&n,&m,&k,&sum))//&&(n+m+k+sum))
{
if(!(n||m||k||sum))
break;
//scanf("%d",&sum);
memset(give,false,sizeof(give));
memset(out,false,sizeof(out));
for(int i=1;i<=sum;i++)
{
int cur;
Point temp;
scanf("%d",&cur);
temp.z=cur/(n*m);
temp.y=(cur%(n*m))/n;
temp.x=(cur%(n*m))%n;
give[temp.x][temp.y][temp.z]=true;
pp[i]=temp;
}
for(int i=0;i<n;i++)
for(int q=0;q<k;q++)
{
dfs(i,0,q);
dfs(i,m-1,q);
}
for(int i=0;i<m;i++)
for(int j=0;j<k;j++)
{
dfs(0,i,j);
dfs(n-1,i,j);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
dfs(i,j,0);
dfs(i,j,k-1);
}
//printf("cnt:%d\n",cnt);
//system("pause");
int ans=0;
for(int i=1;i<=sum;i++)
{
for(int j=0;j<6;j++)
{
int xx=pp[i].x+dir[j][0];
int yy=pp[i].y+dir[j][1];
int zz=pp[i].z+dir[j][2];
if(!iscan(xx,yy,zz))
ans++;
else if(out[xx][yy][zz])
ans++;
}
// printf("\ni:%d x:%d y:%d z:%d ans:%d\n",i,pp[i].x,pp[i].y,pp[i].z,ans);
//system("pause");
}
printf("The number of faces needing shielding is %d.\n",ans);
}
return 0;
}