Description
找到一个边数最小的格点多边形使得周长等于L,若有多解,要找到最长边和最短边相差最短的。
Solution
- 所有边为整数。
- L=2无解。
- L为奇数无解:
- 对于其中的一条边连接了两个点
(x1,y1) 和(x2,y2)。 - c2=(x1−x2)2+(y1−y2)2 。
- 若c为奇数,
x 或y的奇偶性会有一个发生改变。
- 若
c 为偶数,x和y 的奇偶性会同时发生改变或同时不改变。 - L为奇数,说明边长为奇数的边有奇数条,而多边形是从某一点出发回到这点,最终
x 和y的奇偶性与最初不可能相同。与xn=x0 且yn=y0矛盾。
- L≡0(mod4)可以组成一个边长为L4的正方形
- L≡2(mod4)可以组成一个边长分别为L+24,L−24的矩形。
- 关于是否存在整点的三角形,只需要枚举第一象限内合法的点。
tc的评测机是真的快~~
// BEGIN CUT HERE
// END CUT HERE
#line 5 "FindPolygons.cpp"
#include <bits/stdc++.h>
using namespace std;
const int INF = 1 << 30;
const int N = 5050;
typedef pair<int, int> Pairs;
short s[N * N];
int ans;
vector<Pairs> p;
class FindPolygons {
public:
inline int Abs(int x) {
return x < 0 ? -x : x;
}
double minimumPolygon(int L) {
//$CARETPOSITION$
if (L & 1) return -1;
if (L == 2) return -1;
for (int i = 1; i <= L; i++)
s[i * i] = i;
p.clear();
for (int i = 0; i <= L / 2; i++)
for (int j = 0; j * j + i * i <= L * L / 4; j++)
if ((i || j) && s[i * i + j * j]) {
p.push_back(Pairs(i, j));
}
ans = INF;
for (int i = 0; i < p.size(); i++) {
Pairs u = p[i]; int v, x = u.first, y = u.second, a, b, c;
a = s[x * x + y * y];
for (int j = i + 1; j < p.size(); j++) {
Pairs v = p[j];
if (u == v) continue;
int xx = v.first, yy = v.second;
b = s[xx * xx + yy * yy];
c = (x - xx) * (x - xx) + (y - yy) * (y - yy);
if (c > L * L) continue; c = s[c];
if (!c) continue; if (a + b + c != L) continue;
if (x * yy == xx * y) continue;
ans = min(ans, max(Abs(a - b), max(Abs(b - c), Abs(c - a))));
}
}
if (ans == INF) ans = (L >> 1) & 1;
return ans;
}
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = 4; double Arg1 = 0.0; verify_case(0, Arg1, minimumPolygon(Arg0)); }
void test_case_1() { int Arg0 = 5; double Arg1 = -1.0; verify_case(1, Arg1, minimumPolygon(Arg0)); }
void test_case_2() { int Arg0 = 12; double Arg1 = 2.0; verify_case(2, Arg1, minimumPolygon(Arg0)); }
void test_case_3() { int Arg0 = 4984; double Arg1 = 819.0; verify_case(3, Arg1, minimumPolygon(Arg0)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main(void) {
FindPolygons ___test;
___test.minimumPolygon(16);
___test.run_test(-1);
system("pause");
}
// END CUT HERE
- 对于其中的一条边连接了两个点
(x1,y1) 和(x2,y2)。 - c2=(x1−x2)2+(y1−y2)2 。
- 若c为奇数,
x 或y的奇偶性会有一个发生改变。 - 若
c 为偶数,x和y 的奇偶性会同时发生改变或同时不改变。 - L为奇数,说明边长为奇数的边有奇数条,而多边形是从某一点出发回到这点,最终
x 和y的奇偶性与最初不可能相同。与xn=x0 且yn=y0矛盾。
- L≡0(mod4)可以组成一个边长为L4的正方形
- L≡2(mod4)可以组成一个边长分别为L+24,L−24的矩形。
- 关于是否存在整点的三角形,只需要枚举第一象限内合法的点。
tc的评测机是真的快~~
// BEGIN CUT HERE
// END CUT HERE
#line 5 "FindPolygons.cpp"
#include <bits/stdc++.h>
using namespace std;
const int INF = 1 << 30;
const int N = 5050;
typedef pair<int, int> Pairs;
short s[N * N];
int ans;
vector<Pairs> p;
class FindPolygons {
public:
inline int Abs(int x) {
return x < 0 ? -x : x;
}
double minimumPolygon(int L) {
//$CARETPOSITION$
if (L & 1) return -1;
if (L == 2) return -1;
for (int i = 1; i <= L; i++)
s[i * i] = i;
p.clear();
for (int i = 0; i <= L / 2; i++)
for (int j = 0; j * j + i * i <= L * L / 4; j++)
if ((i || j) && s[i * i + j * j]) {
p.push_back(Pairs(i, j));
}
ans = INF;
for (int i = 0; i < p.size(); i++) {
Pairs u = p[i]; int v, x = u.first, y = u.second, a, b, c;
a = s[x * x + y * y];
for (int j = i + 1; j < p.size(); j++) {
Pairs v = p[j];
if (u == v) continue;
int xx = v.first, yy = v.second;
b = s[xx * xx + yy * yy];
c = (x - xx) * (x - xx) + (y - yy) * (y - yy);
if (c > L * L) continue; c = s[c];
if (!c) continue; if (a + b + c != L) continue;
if (x * yy == xx * y) continue;
ans = min(ans, max(Abs(a - b), max(Abs(b - c), Abs(c - a))));
}
}
if (ans == INF) ans = (L >> 1) & 1;
return ans;
}
// BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = 4; double Arg1 = 0.0; verify_case(0, Arg1, minimumPolygon(Arg0)); }
void test_case_1() { int Arg0 = 5; double Arg1 = -1.0; verify_case(1, Arg1, minimumPolygon(Arg0)); }
void test_case_2() { int Arg0 = 12; double Arg1 = 2.0; verify_case(2, Arg1, minimumPolygon(Arg0)); }
void test_case_3() { int Arg0 = 4984; double Arg1 = 819.0; verify_case(3, Arg1, minimumPolygon(Arg0)); }
// END CUT HERE
};
// BEGIN CUT HERE
int main(void) {
FindPolygons ___test;
___test.minimumPolygon(16);
___test.run_test(-1);
system("pause");
}
// END CUT HERE