《算法竞赛入门经典2ndEdition 》习题3-10 盒子(Box, Uva1587)

说说我的思路,每个盒子读入12个数,扫描,每找到一个数,就在12个数中找未被置零的数中与其相同的并置零(最开始的也置零),如果达到四个就break,然后继续找,如果扫描结束还未达到四个,就说明IMPOSSIBLE,
当12个数都空了,如果还未判断出IMPOSSIBLE,就利用在读入数据时计算出的每个面的面积,像刚才一样,6个数,找到一个未置零的,就在6个中找与其相同的,找到了,也置零,然后break,继续找,如果没找到,那么IMPOSSIBLE,
如果还未IMPOSSIBLE,那么输出POSSIBLE。

代码见下:

#include 
#include 
#include 

using namespace std;

int rec[16],square[10];

int main()
{     
  freopen("New Text Document.txt","r",stdin);
  freopen("Output.txt","w",stdout);
  int x, y;
  int flag;
  while(scanf("%d%d", &x, &y) != EOF)
  {
    rec[0] = x;
    rec[1] = y;
    square[0] = x * y;
    for(int i = 2; i < 12; i++) 
    {
      scanf("%d", &rec[i]);
      if(i%2) square[i/2] = rec[i] * rec[i-1];
    }
    //for(int i = 0; i < 6; i++) printf("%d ", square[i]);
    for(int i = 0; i < 12; i++)
      if(rec[i] != 0)
      {
        flag = 0;
        x = rec[i];
        for(int i = 0; i < 12; i++)
        {
          if(rec[i] == x) 
          {
            flag++;
            rec[i] = 0;
          }
          if(flag == 4) break;
        }
        if(flag != 4)
        {
          printf("IMPOSSIBLE\n");
          flag = -1;
          break;
        } 
      }
    if(flag != -1) 
    {
      for(int i = 0; i < 6; i++)
      if(square[i] != 0)
      {
        flag = 0;
        x = square[i];
        for(int i = 0; i < 6; i++)
        {
          if(square[i] == x) 
          {
            flag++;
            square[i] = 0;
          }
          if(flag == 2) break;
        }
        if(flag != 2)
        {
          printf("IMPOSSIBLE\n");
          flag = -1;
          break;
        } 
      }
      if(flag != -1) 
      printf("POSSIBLE\n");
    } 
  }
  return 0;
}

个人感觉我的方法还可以,这里有一个别人的代码,还是推荐去阅读原文:http://blog.csdn.net/kun768/article/details/43701899

#include 
using namespace std;

struct face{
    int x, y;
}a[6];
bool check()
{
    if(memcmp(a, a+1, sizeof(face)) || memcmp(a+2, a+3, sizeof(face)) || memcmp(a+4, a+5, sizeof(face))) return false;
    if(a[0].x!=a[2].x || a[0].y!= a[4].x || a[2].y!=a[4].y) return false;
    return true;
}
int main()
{
    while(cin >> a[0].x >> a[0].y >> a[1].x >> a[1].y >> a[2].x >> a[2].y >> a[3].x >> a[3].y >> a[4].x >> a[4].y >> a[5].x >> a[5].y){
        for(int i = 0; i < 6; ++i)
            if(a[i].x < a[i].y)
                swap(a[i].x, a[i].y);
        sort(a, a+6, [](const face a, const face b) {return a.x==b.x ? (a.y > b.y) : (a.x > b.x);});
        printf("%s\n", check() ? "POSSIBLE" : "IMPOSSIBLE");
    }
    return 0;
}

下面这个是在网上看到的程序感觉思路不错,很有启发,
贴上来。

   只要用一堆疯狂的条件分支就能解答此题了,如[KinderRiven](http://blog.csdn.net/u013451221/article/details/37672039)的代码。不过这里我更乐意把数据“标准化”,然后用C++构造“Face类”来求解。
   首先构造一个宽w一定不小于高h的“面类(Face)”,并且按h为第一级,w为第二级准则从小到大排序。如果是能组成长方体的,边长肯定只有三种值,不妨设从小到大依次为a,b,c。则输入的6个面排序后,一定满足以下分布:

《算法竞赛入门经典2ndEdition 》习题3-10 盒子(Box, Uva1587)_第1张图片
首先每种面肯定都出现了两次,即编号0、1相同,编号2、3相同,编号4、5相同。把这个准则,设计为测试函数test1。
接下来,编号0的h一定与编号2的h相等,编号0的w一定与编号4的h相等,编号2的w一定与编号4的w相等。把这个准则,设计为测试函数test2。
满足上述两个测试,是数据能组合成长方体的充要条件。

#include 
#include 
#include 
using namespace std;

struct Face{
    int h, w;
    void make(int x, int y) {
        h = min(x,y);
        w = max(x,y);
    }
    bool operator < (const Face& b) const {
        if (h == b.h) return w < b.w;
        else return h < b.h;
    }
    bool operator == (const Face& b) const {
        return (h == b.h) && (w == b.w);
    }
};
vector A(6);

int test1() {
    for (int i = 0; i < 6; i += 2) if (!(A[i]==A[i+1])) return 0;
    return 1;
}

int test2() {
    if (A[0].h==A[2].h && A[0].w==A[4].h && A[2].w==A[4].w) return 1;
    else return 0;
}

int main() {
    int x, y;
    while (cin >> x >> y) {
        A[0].make(x, y);
        for (int i = 1; i < 6; i++) {
            cin >> x >> y;
            A[i].make(x, y);
        }
        sort(A.begin(), A.end());
        if (test1() && test2()) cout << "POSSIBLE\n";
        else cout << "IMPOSSIBLE\n";
    }
    return 0;

}

上述代码原文:http://blog.csdn.net/code4101/article/details/38303607

你可能感兴趣的:(算法竞赛入门经典,uva)