C ++检测方块

时间:2014-04-24 16:19:54

标签: c++

我构建了以下代码来读取4对坐标来计算它是否为正方形:

#include <iostream>
using namespace std;

struct {
    int x;
    int y;
}a[10];

int dist(int x1, int y1, int x2, int y2)
{
// function to compute the (square of the) distance between two points
    int c1, c2;
    c1 = x2-x1;
    c2 = y2-y1;
    return (c1*c1)+(c2*c2);
}

int main()
{
    int d1, d2, d3, d4;
    for (int i=1; i<=4; i++)
    {
        cout << 'X' << i << '='; cin >> a[i].x;
        cout << 'Y' << i << '='; cin >> a[i].y;
    }
    d1 = dist(a[1].x, a[1].y, a[2].x, a[2].y);
    d2 = dist(a[2].x, a[2].y, a[3].x, a[3].y);
    d3 = dist(a[3].x, a[3].y, a[4].x, a[4].y);
    d4 = dist(a[4].x, a[4].y, a[1].x, a[1].y);
    if(d1==d2 && d1==d3 && d1==d4)
        cout << "Is a square";
    else
        cout << "Is not a square";
    return 0;
}

代码运行良好,但我想读取多个坐标(超过四个),并检查四个点的每个可能组合,看看它们是否形成正方形。

我无法弄清楚如何扩展上述方法以使用超过四个点作为输入(并从中选择所有四个组合);请有人给我一个提示/手吗?

2 个答案:

答案 0 :(得分:0)

这听起来像是一个完整的图形问题。由于所有点都是int,我可以想到的一件事是进行深度优先搜索,没有重复,距离^ 2作为权重。而且你需要一个双伪图来保持角度信息(一个布尔值足以直角v.s.非直角)。

从点0开始,步进到最近的邻居1,然后从邻居1开始,找到它的邻居2,3,4 ...,并按两个标准过滤:距离和角度。每次深度优先搜索最多只需要4步,因为只有4个边。

遍历所有点和预订访问点,您可以跟踪在此期间制作的广场数量。

答案 1 :(得分:0)

以下是一些检查四个点的所有组合以查看它们是否为正方形的代码。请注意,您测试“方形”的原始方法是错误的 - 首先,即使以正确的顺序给出点,钻石形状(错误地)也会被称为“方形”;第二,如果以“错误”的顺序给出点数,则正方形可能看起来不正方形。

我解决了这两个问题。另外,我创建了一个简单的嵌套循环,它可以生成四个点的所有可能组合并对它们进行测试;这可以提高效率(例如,如果点1,2和3不形成“等腰直角三角形”,那么测试第四点是没有意义的 - 所以你可以通过不测试所有时间来节省大量时间其他可能的点)。我将把它留下一段时间。

我没有费心去编写代码的“输入N点”部分 - 我不认为那是你在努力的方面。如果我认为这是错误的,请告诉我。

#include <iostream>

typedef struct{
  int x;
  int y;
} point;

int isSquare (point *p1, point *p2, point *p3, point *p4) {
double dx, dy;
double dd[6];
point *pp[4];

pp[0]=p1; pp[1]=p2; pp[2]=p3; pp[3]=p4;
int ii, jj, kk, nn;
kk = 0;
// loop over all combinations of first and second point
// six in all
for(ii=0; ii<3; ii++) {
  for(jj=ii+1; jj<4; jj++) {
    dx = pp[ii]->x - pp[jj]->x;
    dy = pp[ii]->y - pp[jj]->y;
    dd[kk]= dx*dx + dy*dy;
    if (dd[kk]==0) return 0; // two identical points: not a square
    if(kk>1) {
      for(nn= 0; nn < kk-1; nn++) {
        // if both are "sides", we expect their length to be the same;
        // if one is a diagonal and the other a side, their ratio is 2
        // since we are working with the square of the number
        if (!(((2*dd[nn] == dd[kk] ) || (dd[nn] == dd[kk]) || 2*dd[kk] == dd[nn] ))) return 0;
      }
    }
     kk++;
  }
}
return 1; // got here: all combinations tested OK, we have a square

}

int main(void) {
  // pick ten numbers - chosen so there are two squares
  point p[10]={{1,2},{3,2},{1,4},{7,8},{2,4},{3,4},{6,7},{8,7},{2,5},{3,5}};
  double d2[10][10];
  int ii, jj, kk, ll;
  // loop over all possible combinations: 
  // since there are just four to pick we can hard-wire the loop
  for(ii=0; ii<7; ii++) {
    for(jj = ii+1; jj<8; jj++) {
      for(kk = jj+1; kk<9; kk++) {
        for(ll = kk+1; ll<10; ll++) {
          if(isSquare(p+ii, p+jj, p+kk, p+ll)) {
            std::cout << "combination: " << ii << "," << jj << "," << kk << "," << ll << " is a square\n";
          }
        }
      }
    }
  }
}

输出:

combination: 0,1,2,5 is a square
combination: 4,5,8,9 is a square