UVa1587 盒子

前言

第一次刷题,ac的感觉真的很棒!

题目

题目

大意是说,输入6个面,判断是否是个长方体。

思路

根据长方体的特质来判断,比如说6个面中3个面是相互对应的,只有3条不同的边等等。

我就知道我肯定会卡在输入输出这上面一次的😂。

给大家看看我的ac...

实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/**
 * 习题3-10 盒子
 * 判断是否是长方形,用6个面,其实就是3个面
 */
struct Panel {
    int width;
    int height;
}panels[6];
int lines[12];

// 判断是否面之间的长和宽是否相等
int isPanelsEquality(struct Panel panel1, struct Panel panel2) {
    if ((panel1.width == panel2.width && panel1.height == panel2.height) ||
        (panel1.width == panel2.height && panel1.height == panel2.width)) {
        return 1;
    }
    return 0;
}

// 对边长进行排序
int* Bublesort(int a[],int n)
{
    /* 气泡法要排序n次*/
    for(int j = 0; j < n - 1; j++) {
        for(int i = 0; i < n-j-1; i++) {
            if(a[i] > a[i+1]) {
                int k = a[i];
                a[i] = a[i+1];
                a[i+1] = k;
            }
        }
    }
    return a;
}

void caculate15() {
    int w, h;
    while (scanf("%d%d", &w, &h) != EOF) {
        panels[0].width = w;
        panels[0].height = h;
        lines[0] = w;
        lines[1] = h;

        for (int i = 1; i < 6; i++) {
            scanf("%d%d", &w, &h);
            panels[i].width = w;
            panels[i].height = h;
            lines[i*2] = w;
            lines[i*2+1] = h;
        }

        int hash[6];
        int visited[6];
        memset(hash, 0, sizeof(hash));
        memset(visited, 0, sizeof(visited));

        // 面是两两相等
        for (int i = 0; i < 6; i++) {
            if (visited[i] == 1) {
                continue;
            }
            visited[i] = 1;
            hash[i]++;

            for (int j = 0; j < 6; j++) {
                if (visited[j] != 0 || i == j) {
                    continue;
                }
                if (isPanelsEquality(panels[i], panels[j])) {
                    visited[j] = 1;
                    hash[i]++;
                    break;
                }
            }
        }

        // hash中的个数必然是0或者2
        int result = 1;
        for (int i = 0; i < 6; i++) {
            if (visited[i] == 0 || (hash[i] != 2 && hash[i] != 0)) {
                result = 0;
                break;
            }
        }

        if (result) {
            // hash中存在3个2,表示面两两对应
            int twocnt = 0;
            for (int i = 0; i < 6; i++) {
                if (hash[i] == 2) {
                    twocnt++;
                }
            }

            if (twocnt != 3) {
                result = 0;
            } else {
                result = 1;
            }

            if (result) {
                // 还有面和面之间是有联系的,一个面和另外一个面是通过一条线联系,也就是说一共有4条相等的直线
                // 统计12条直线里是否有4条相等的直线
                int* line_hash = Bublesort(lines, 12);

                if (line_hash[0] != line_hash[3] || line_hash[4] != line_hash[7] || line_hash[8] != line_hash[11]) {
                    result = 0;
                }
            }
        }

        if (result) {
            printf("POSSIBLE\n");
        }
        else {
            printf("IMPOSSIBLE\n");
        }
    }
}

int main() {
    caculate15();
    return 0;
}

思路已经说的很清楚了,纯c写代码真的很烦,明明c++11可以写得更快的。下面这个方法也是用纯c写的,来自台湾同胞~

void caculate16() {
    int w, h, pallet[6][2] = {};
    // 第一个面
    while (scanf("%d%d", &w, &h) != EOF) {
        if (w < h)
            pallet[0][0] = w, pallet[0][1] = h;
        else
            pallet[0][0] = h, pallet[0][1] = w;

        // 剩余的面
        int i;
        for (i = 1; i < 6; i++) {
            scanf("%d%d", &w, &h);
            if (w < h)
                pallet[i][0] = w, pallet[i][1] = h;
            else
                pallet[i][0] = h, pallet[i][1] = w;
        }

        int used[6] = {}, ok = 1;
        memset(used, 0, sizeof(used));

        int side[3][2], count = 0; //3个不同的面
        memset(side, 0, sizeof(side));

        // side保存下来三个面的2条边
        for (i = 0; i < 6; i++) {
            if (used[i])
                continue;
            for (int j = i + 1; j < 6; j++)
                if (!used[j] && pallet[i][0] == pallet[j][0] && pallet[i][1] == pallet[j][1]) {
                    used[i] = used[j] = 1;
                    break;
                }
            if (!used[i])
                break;

            side[count][0] = pallet[i][0];
            side[count][1] = pallet[i][1];

            count++;
        }

        // 不存在没有访问过的面
        for (i = 0; i < 6; i++)
            if (!used[i])
                ok = 0;

        if (ok) {
            ok = 0;
            //用那 3 塊去拚看看矩形的 上方一片、側邊兩片
            for (i = 0; i <= 1; i++) {
                for (int j = 0; j <= 1; j++) {
                    // 在这里先进行假定第一个面和第二个面相等(因为两个面之间必然存在相等的边)
                    if (side[0][i] == side[1][j]) {
                        // 同样的情况
                        if (side[0][!i] == side[2][0] && side[2][1] == side[1][!j])
                            ok = 1;
                        else if (side[0][!i] == side[2][1] && side[2][0] == side[1][!j])
                            ok = 1;
                    }
                }
            }
        }

        puts(ok ? "POSSIBLE" : "IMPOSSIBLE");
    }
}

好吧,我要开始用c++11开始写了,既方便由可以学习c++11。

posted @ 2017-03-11 23:12  banananana  阅读(402)  评论(0编辑  收藏  举报