练习floodfill很好的题。第一次考虑从内部有模块的点开始floodfill,发现无法识别内部空仓和外部空仓。反向思考,从外部空仓进入模块,得解。
int b[60][60][60];
bool used[216000];
int q[216000];
int N, M, K, L;
int dir[6][3] =
{
{ 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }
};
int getx ( int n, int m, int k )
{
return ( k * M + m ) * N + n;
}
void setx ( int x, int &n, int &m, int &k )
{
k = x / ( N * M );
x = x % ( N * M );
m = x / N;
n = x % N;
}
int main ()
{
//freopen ( "in.txt", "r", stdin );
while ( scanf ( "%d%d%d%d", &N, &M, &K, &L ) && N )
{
memset ( b, 0, sizeof ( b ) );
int i, x, n, m, k;
for ( i = 0; i < L; i ++ )
{
scanf ( "%d", &x );
setx ( x, n, m, k );
b[n][m][k] = 1;
}
memset ( used, 0, sizeof ( used ) );
int op, ed;
// 对外层平面的所有0值点进行floodfill,进入1值点的即计数
int count = 0;
for ( n = 0; n < N; n ++ )
{
for ( m = 0; m < M; m ++ )
{
for ( k = 0; k < K; k ++ )
{
if ( n != 0 && n != N - 1 && m != 0 && m != M - 1 && k != 0 && k != K - 1 )
continue;
if ( b[n][m][k] == 0 )
{
b[n][m][k] = 2;
int x = getx ( n, m, k );
q[0] = x;
for ( op = -1, ed = 0; op ++ < ed; )
{
int xx = q[op];
int kk, mm, nn;
setx ( xx, nn, mm, kk );
int l;
for ( l = 0; l < 6; l ++ )
{
int nnn = nn + dir[l][0], mmm = mm + dir[l][1], kkk = kk + dir[l][2];
if ( nnn < 0 || nnn >= N || mmm < 0 || mmm >= M || kkk < 0 || kkk >= K )
continue;
if ( b[nnn][mmm][kkk] == 1 )
count ++;
if ( b[nnn][mmm][kkk] == 0 )
{
b[nnn][mmm][kkk] = 2;
int xxx = getx ( nnn, mmm, kkk );
q[++ ed] = xxx;
}
}
}
}
}
}
}
for ( n = 0; n < N; n ++ )
{
for ( m = 0; m < M; m ++ )
{
if ( b[n][m][0] == 1 )
count ++;
if ( b[n][m][K - 1] == 1 )
count ++;
}
}
for ( k = 0; k < K; k ++ )
{
for ( m = 0; m < M; m ++ )
{
if ( b[0][m][k] == 1 )
count ++;
if ( b[N - 1][m][k] == 1 )
count ++;
}
}
for ( n = 0; n < N; n ++ )
{
for ( k = 0; k < K; k ++ )
{
if ( b[n][0][k] == 1 )
count ++;
if ( b[n][M - 1][k] == 1 )
count ++;
}
}
printf ( "The number of faces needing shielding is %d./n", count );
}
return 0;
}