题目意思很简单,已知长方体表面上两个点,要求这两个点的最短表面距离。
一开始我是手推展开方式的,后来发现一共有12种展开情况,手写坐标变换相当麻烦。
然后改用递归方式展开。具体方式是先把第一个点转到底面(xOy平面),然后对四个方向把底面翻开,把翻到的面作为新的底面。递归做下去,一直到第二个点也翻到底面上。
下面是我的代码:
/**//*************************************************************************
Author: WHU_GCC
Created Time: 2008-1-23 19:34:33
File Name: 1444.cpp
Description:
************************************************************************/
#include <iostream>
using namespace std;
#define out(x) (cout << #x << ": " << x << endl)
typedef long long int64;
const int maxint = 0x7FFFFFFF;
const int64 maxint64 = 0x7FFFFFFFFFFFFFFFLL;
template <class T> void show(T a, int n) { for (int i = 0; i < n; ++i) cout << a[i] << ' '; cout << endl; }
template <class T> void show(T a, int r, int l) { for (int i = 0; i < r; ++i) show(a[i], l); cout << endl; }
int ans;
void walk(int i, int j, int x0, int y0, int x, int y, int z, int l, int w, int h)
{
if (z == 0)
ans <?= (x0 - x) * (x0 - x) + (y0 - y) * (y0 - y);
else
{
if (i >= 0 && i < 2)
walk(i + 1, j, x0, y0 - w, x, z, w - y, l, h, w);
if (i <= 0 && i > -2)
walk(i - 1, j, x0, y0 + h, x, h - z, y, l, h, w);
if (j >= 0 && j < 2)
walk(i, j + 1, x0 - l, y0, z, y, l - x, h, w, l);
if (j <= 0 && j > -2)
walk(i, j - 1, x0 + h, y0, h - z, y, x, h, w, l);
}
}
int main()
{
int l, w, h, x1, y1, z1, x2, y2, z2;
while (scanf("%d%d%d", &l, &w, &h) != EOF)
{
scanf("%d%d%d", &x1, &y1, &z1);
scanf("%d%d%d", &x2, &y2, &z2);
if (z1 != 0 && z1 != h)
{
if (y1 != 0 && y1 != w)
{
swap(x1, z1);
swap(x2, z2);
swap(l, h);
}
else
{
swap(y1, z1);
swap(y2, z2);
swap(w, h);
}
}
if (z1 == h)
{
z1 = 0;
z2 = h - z2;
}
ans = maxint;
walk(0, 0, x1, y1, x2, y2, z2, l, w, h);
printf("%d\n", ans);
}
return 0;
}