模拟+搜索poj 1063 Flip and Shift

题目链接:

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值