UVa1587 盒子
2017-03-11 23:12
323 查看
前言
第一次刷题,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。
相关文章推荐