Sicily 1629. Area of Polycubes

1629. Area of Polycubes

Constraints

Time Limit: 5 secs, Memory Limit: 32 MB

Description

polycube is a solid made by gluing together unit cubes (one unit on each edge) on one or more faces. The figure in the lower-left is not a polycube because some cubes are attached along an edge.

For this problem, the polycube will be formed from unit cubes centered at integer lattice points in 3-space. The polycube will be built up one cube at a time, starting with a cube centered at (0,0,0). At each step of the process (after the first cube), the next cube must have a face in common with a cube previously included and not be the same as a block previously included. For example, a 1-by-1-by-5 block (as shown above in the upper-left polycube) could be built up as:


(0,0,0) (0,0,1) (0,0,2) (0,0,3) (0,0,4)


and a 2-by-2-by-2 cube (upper-right figure) could be built as:


(0,0,0) (0,0,1) (0,1,1) (0,1, 0) (1,0,0) (1,0,1) (1,1,1) (1,1, 0)


Since the surface of the polycube is made up of unit squares, its area is an integer.


Write a program which takes as input a sequence of integer lattice points in 3-space and determines whether is correctly forms a polycube and, if so, what the surface area of the polycube is.

Input

The first line of input contains a single integer N , (1≤N≤1000) which is the number of data sets that follow. Each data set consists of multiple lines of input. The first line contains the number of points P , (1 = P = 100) in the problem instance. Each succeeding line contains the centers of the cubes, eight to a line (except possibly for the last line). Each center is given as 3 integers, separated by commas. The points are separated by a single space.

Output

For each data set, you should generate one line of output with the following values: The data set number as a decimal integer (start counting at one), a space and the surface area of the polycube if it is correctly formed, OR, if it is not correctly formed, the string ``NO" a space and the index (starting with 1) of the first cube which does not share a face with a previous cube. Note that the surface area includes the area of any included holes.

Sample Input

4 
5 
0,0,0 0,0,1 0,0,2 0,0,3 0,0,4 
8 
0,0,0 0,0,1 0,1,0 0,1,1 1,0,0 1,0,1 1,1,0 1,1,1 
4 
0,0,0 0,0,1 1,1,0 1,1,1 
20 
0,0,0 0,0,1 0,0,2 0,1,2 0,2,2 0,2,1 0,2,0 0,1,0 
1,0,0 2,0,0 1,0,2 2,0,2 1,2,2 2,2,2 1,2,0 2,2,0 
2,1,0 2,1,2 2,0,1 2,2,1

Sample Output

1 22 
2 24 
3 NO 3 

4 72

// Problem#: 1629
// Submission#: 3593580
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
/*
 * Polycube Solution
 *
 * by Fred Pickel
 * October 2008
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX_PROBS   1000
#define EPS .001
#define ERR .001

char inbuf[512];
int nCubes;
int points[110][3];

int ReadDataSet(int index)
{
    int baseIndex, nLeft;
    if(fgets(&(inbuf[0]), 255, stdin) == NULL)
    {
        fprintf(stderr, "read of cube count failed on problem %d\n", index);
        return -1;
    }
    inbuf[255] = 0;
    nCubes = atoi(&(inbuf[0]));
    if((nCubes <= 0) || (nCubes > 100))
    {
        fprintf(stderr, "cube count %d out of range (1-100) on problem %d\n",
            nCubes, index);
        return -2;
    }
    baseIndex = 0;
    nLeft = nCubes;
    while(nLeft >= 8)
    {
        if(fgets(&(inbuf[0]), 255, stdin) == NULL)
        {
            fprintf(stderr, "read of cubes starting %d failed on problem %d\n",
                baseIndex, index);
            return -3;
        }
        inbuf[255] = 0;
        if(sscanf(&(inbuf[0]),
            "%d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d",
            &points[baseIndex+0][0], &points[baseIndex+0][1], &points[baseIndex+0][2], 
            &points[baseIndex+1][0], &points[baseIndex+1][1], &points[baseIndex+1][2], 
            &points[baseIndex+2][0], &points[baseIndex+2][1], &points[baseIndex+2][2], 
            &points[baseIndex+3][0], &points[baseIndex+3][1], &points[baseIndex+3][2], 
            &points[baseIndex+4][0], &points[baseIndex+4][1], &points[baseIndex+4][2], 
            &points[baseIndex+5][0], &points[baseIndex+5][1], &points[baseIndex+5][2], 
            &points[baseIndex+6][0], &points[baseIndex+6][1], &points[baseIndex+6][2], 
            &points[baseIndex+7][0], &points[baseIndex+7][1], &points[baseIndex+7][2]) != 24)
        {
            fprintf(stderr, "scan of cubes starting %d failed on problem %d\n",
                baseIndex, index);
            return -4;
        }
        baseIndex += 8;
        nLeft -= 8;
    }
    // do any left
    if(nLeft > 0)
    {
        if(fgets(&(inbuf[0]), 255, stdin) == NULL)
        {
            fprintf(stderr, "read of cubes starting %d failed on problem %d\n",
                baseIndex, index);
            return -3;
        }
        inbuf[255] = 0;
        if(sscanf(&(inbuf[0]),
            "%d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d %d,%d,%d",
            &points[baseIndex+0][0], &points[baseIndex+0][1], &points[baseIndex+0][2], 
            &points[baseIndex+1][0], &points[baseIndex+1][1], &points[baseIndex+1][2], 
            &points[baseIndex+2][0], &points[baseIndex+2][1], &points[baseIndex+2][2], 
            &points[baseIndex+3][0], &points[baseIndex+3][1], &points[baseIndex+3][2], 
            &points[baseIndex+4][0], &points[baseIndex+4][1], &points[baseIndex+4][2], 
            &points[baseIndex+5][0], &points[baseIndex+5][1], &points[baseIndex+5][2], 
            &points[baseIndex+6][0], &points[baseIndex+6][1], &points[baseIndex+6][2], 
            &points[baseIndex+7][0], &points[baseIndex+7][1], &points[baseIndex+7][2]) != 3*nLeft)
        {
            fprintf(stderr, "scan of cubes starting %d failed on problem %d\n",
                baseIndex, index);
            return -4;
        }
    }
    return 0;
}

int IsNbr(int pt1[3], int pt2[3])
{
    if((pt1[0] == pt2[0]) && (pt1[1] == pt2[1]))
    {
        if(pt1[2] == pt2[2])
        {   // same
            return -1;
        }
        if(pt1[2] == (pt2[2]+1))
        {
            return 1;
        }
        if(pt1[2] == (pt2[2]-1))
        {
            return 1;
        }
    }
    if((pt1[0] == pt2[0]) && (pt1[2] == pt2[2]))
    {
        if(pt1[1] == (pt2[1]+1))
        {
            return 1;
        }
        if(pt1[1] == (pt2[1]-1))
        {
            return 1;
        }
    }
    if((pt1[2] == pt2[2]) && (pt1[1] == pt2[1]))
    {
        if(pt1[0] == (pt2[0]+1))
        {
            return 1;
        }
        if(pt1[0] == (pt2[0]-1))
        {
            return 1;
        }
    }
    return 0;
}
// find out how many previous cubes have a face in common with cube
// centered at pt return -1 if same as previous else count of faces in common
int CountNbrs(int pt[3], int prevPoint)
{
    int i, ret, cnt;
    for(i = 0, cnt = 0; i <= prevPoint ; i++)
    {
        ret = IsNbr(pt, &(points[i][0]));
        if(ret < 0)
        {
            return -1;
        }
        else
        {
            cnt += ret;
        }
    }
    return cnt;
}

int CountArea()
{
    int area, i, cnt;
    area = 6;   // first cube
    for(i = 1; i < nCubes ; i++)
    {
        cnt = CountNbrs(&(points[i][0]), i-1);
        if(cnt <= 0)
        {
            return -(i+1);
        }
        else
        {
            area += (6 - 2*cnt);
        }
    }
    return area;
}

int main()
{
    int probCnt, curProb, ret;

    if(fgets(&(inbuf[0]), 255, stdin) == NULL)
    {
        fprintf(stderr, "read failed on problem count\n");
        return -1;
    }
    inbuf[255] = 0;
    probCnt = atoi(&(inbuf[0]));
    if((probCnt < 1) || (probCnt > MAX_PROBS))
    {
        fprintf(stderr, "Problem count %d not in range 1...%d\n", probCnt, MAX_PROBS);
        return -2;
    }
    for(curProb = 1; curProb <= probCnt ; curProb++)
    {
        if((ret = ReadDataSet(curProb)) != 0)
        {
            fprintf(stderr, "ReadDataSet returned %d on problem %d\n", ret, curProb);
            return -3;
        }
        ret = CountArea();
        if(ret < 0)
        {
            printf("%d NO %d\n", curProb, -ret);
        }
        else
        {
            printf("%d %d\n", curProb, ret);
        }
    }
    return 0;
}                                 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值