#include <array>
#include <chrono>
#include <iostream>
struct point {
int x;
int y;
};
template<std::size_t N>
bool create_polygon_jit(std::array<point, N>& points, int n, int target_n, int gridsize, int curr_area, int& min_area, std::array<point, N>& soln)
{
if (n >= 3)
{
int x1 = points[n - 3].x - points[n - 2].x, y1 = points[n - 3].y - points[n - 2].y;
int x2 = points[n - 1].x - points[n - 2].x, y2 = points[n - 1].y - points[n - 2].y;
if (x1 * y2 - x2 * y1 <= 0) // Angle > 180
return false;
if (x1 * x2 + y1 * y2 > 0) // Angle >= 90
return false;
if (points[1].x == 0 and points[n - 1].x == 0)
return true;
int add_area = points[n - 1].x * points[n - 2].y - points[n - 1].y * points[n - 2].x;
if (add_area <= 0)
return true;
curr_area += add_area;
if (curr_area >= min_area)
return true;
if (n == target_n)
{
min_area = curr_area;
soln = points;
return true;
}
int min_i = std::max(0, points[n - 1].x - 3);
int max_i = std::min(gridsize, points[n - 1].x + 4);
int min_j = std::max(- gridsize / 2, points[n - 1].y - 3);
int max_j = std::min(gridsize / 2 + 1, points[n - 1].y + 4);
if (x2 > 0)
{
if (y2 > 0)
{
if (x2 > y2)
{
for (int j = min_j; j < max_j; j++){
for (int i = max_i - 1; i > min_i - 1; i--){
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].x == max_i - 1)
break;
}
}
else
{
for (int j = max_j - 1; j > min_j - 1; j--)
{
for (int i = max_i - 1; i > min_i - 1; i--)
{
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].x == max_i - 1)
break;
}
}
}
else
{
if (x2 > -y2)
{
for (int i = max_i - 1; i > min_i - 1; i--)
{
for (int j = min_j; j < max_j; j++)
{
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].y == min_j)
break;
}
}
else
{
for (int i = min_i; i < max_i; i++)
{
for (int j = min_j; j < max_j; j++)
{
points[n].x = i;
points[n].y = j;
;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].y == min_j)
break;
}
}
}
}
else
{
if (y2 > 0)
{
if (-x2 > y2)
{
for (int i = min_i; i < max_i; i++)
{
for (int j = max_j - 1; j > min_j - 1; j--)
{
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].y == max_j - 1)
break;
}
}
else
{
for (int i = max_i - 1; i > min_i - 1; i--)
{
for (int j = max_j - 1; j > min_j - 1; j--)
{
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].y == max_j - 1)
break;
}
}
}
else
{
if (-x2 > -y2)
{
for (int j = max_j - 1; j > min_j - 1; j--)
{
for (int i = min_i; i < max_i; i++)
{
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].x == min_i)
break;
}
}
else
{
for (int j = min_j; j < max_j; j++)
{
for (int i = min_i; i < max_i; i++)
{
points[n].x = i;
points[n].y = j;
if (!create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln))
break;
}
if (points[n].x == min_i)
break;
}
}
}
}
}
else
{
int min_i = std::max(0, points[n - 1].x - 3);
int max_i = std::min(gridsize, points[n - 1].x + 4);
int min_j = std::max(-gridsize / 2, points[n - 1].y - 3);
int max_j = std::min(gridsize / 2, points[n - 1].y + 4);
for (int i = min_i; i < max_i; i++)
{
for (int j = min_j; j < max_j; j++)
{
points[n].x = i;
points[n].y = j;
create_polygon_jit(points, n + 1, target_n, gridsize, curr_area, min_area, soln);
}
}
}
points[n].x = 0;
points[n].y = 0;
return true;
}
int main() {
using namespace std::chrono;
auto t1 = steady_clock::now();
const int n = 16;
std::array<point, n> points{};
int gridSize = 11;
int minArea = gridSize * gridSize;
std::array<point, n> result;
for (point& p : result){
p.x = 0;
p.y = 0;
}
create_polygon_jit(points, 1, n, gridSize, 0, minArea, result);
std::cout << "Result: ";
for (point& p : result)
std::cout << "("<< p.x << ", " << p.y << ") ";
std::cout << "\nArea: " << minArea << "\n";
auto t2 = steady_clock::now();
auto time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "Time:" << time_span.count() << " seconds.\n";
}
I2luY2x1ZGUgPGFycmF5PgojaW5jbHVkZSA8Y2hyb25vPgojaW5jbHVkZSA8aW9zdHJlYW0+CgpzdHJ1Y3QgcG9pbnQgewoJaW50IHg7CglpbnQgeTsKfTsKCnRlbXBsYXRlPHN0ZDo6c2l6ZV90IE4+CmJvb2wgY3JlYXRlX3BvbHlnb25faml0KHN0ZDo6YXJyYXk8cG9pbnQsIE4+JiBwb2ludHMsIGludCBuLCBpbnQgdGFyZ2V0X24sIGludCBncmlkc2l6ZSwgaW50IGN1cnJfYXJlYSwgaW50JiBtaW5fYXJlYSwgc3RkOjphcnJheTxwb2ludCwgTj4mIHNvbG4pIAp7CglpZiAobiA+PSAzKQoJewoJCWludCB4MSA9IHBvaW50c1tuIC0gM10ueCAtIHBvaW50c1tuIC0gMl0ueCwgeTEgPSBwb2ludHNbbiAtIDNdLnkgLSBwb2ludHNbbiAtIDJdLnk7CgkJaW50IHgyID0gcG9pbnRzW24gLSAxXS54IC0gcG9pbnRzW24gLSAyXS54LCB5MiA9IHBvaW50c1tuIC0gMV0ueSAtIHBvaW50c1tuIC0gMl0ueTsKCQlpZiAoeDEgKiB5MiAtIHgyICogeTEgPD0gMCkgLy8gQW5nbGUgPiAxODAKCQkJcmV0dXJuIGZhbHNlOwoJCWlmICh4MSAqIHgyICsgeTEgKiB5MiA+IDApICAvLyBBbmdsZSA+PSA5MAoJCQlyZXR1cm4gZmFsc2U7CgkJaWYgKHBvaW50c1sxXS54ID09IDAgYW5kIHBvaW50c1tuIC0gMV0ueCA9PSAwKQoJCQlyZXR1cm4gdHJ1ZTsKCgkJaW50IGFkZF9hcmVhID0gcG9pbnRzW24gLSAxXS54ICogcG9pbnRzW24gLSAyXS55IC0gcG9pbnRzW24gLSAxXS55ICogcG9pbnRzW24gLSAyXS54OwoJCWlmIChhZGRfYXJlYSA8PSAwKQoJCQlyZXR1cm4gdHJ1ZTsKCgkJY3Vycl9hcmVhICs9IGFkZF9hcmVhOwoJCWlmIChjdXJyX2FyZWEgPj0gbWluX2FyZWEpCgkJCXJldHVybiB0cnVlOwoKCQlpZiAobiA9PSB0YXJnZXRfbikKCQl7CgkJCW1pbl9hcmVhID0gY3Vycl9hcmVhOwoJCQlzb2xuID0gcG9pbnRzOwoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgoJCWludCBtaW5faSA9IHN0ZDo6bWF4KDAsIHBvaW50c1tuIC0gMV0ueCAtIDMpOwoJCWludCBtYXhfaSA9IHN0ZDo6bWluKGdyaWRzaXplLCBwb2ludHNbbiAtIDFdLnggKyA0KTsKCgkJaW50IG1pbl9qID0gc3RkOjptYXgoLSBncmlkc2l6ZSAvIDIsIHBvaW50c1tuIC0gMV0ueSAtIDMpOwoJCWludCBtYXhfaiA9IHN0ZDo6bWluKGdyaWRzaXplIC8gMiArIDEsIHBvaW50c1tuIC0gMV0ueSArIDQpOwoJCQoJCWlmICh4MiA+IDApCgkJewoJCQlpZiAoeTIgPiAwKQoJCQl7CgkJCQlpZiAoeDIgPiB5MikKCQkJCXsKCQkJCQlmb3IgKGludCBqID0gbWluX2o7IGogPCBtYXhfajsgaisrKXsKCQkJCQkJZm9yIChpbnQgaSA9IG1heF9pIC0gMTsgaSA+IG1pbl9pIC0gMTsgaS0tKXsKCQkJCQkJCXBvaW50c1tuXS54ID0gaTsKCQkJCQkJCXBvaW50c1tuXS55ID0gajsKCQkJCQkJCWlmICghY3JlYXRlX3BvbHlnb25faml0KHBvaW50cywgbiArIDEsIHRhcmdldF9uLCBncmlkc2l6ZSwgY3Vycl9hcmVhLCBtaW5fYXJlYSwgc29sbikpCgkJCQkJCQkJYnJlYWs7CgkJCQkJCX0KCQkJCQkJaWYgKHBvaW50c1tuXS54ID09IG1heF9pIC0gMSkKCQkJCQkJCWJyZWFrOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UKCQkJCXsKCQkJCQlmb3IgKGludCBqID0gbWF4X2ogLSAxOyBqID4gbWluX2ogLSAxOyBqLS0pCgkJCQkJewoJCQkJCQlmb3IgKGludCBpID0gbWF4X2kgLSAxOyBpID4gbWluX2kgLSAxOyBpLS0pCgkJCQkJCXsKCQkJCQkJCXBvaW50c1tuXS54ID0gaTsKCQkJCQkJCXBvaW50c1tuXS55ID0gajsKCgkJCQkJCQlpZiAoIWNyZWF0ZV9wb2x5Z29uX2ppdChwb2ludHMsIG4gKyAxLCB0YXJnZXRfbiwgZ3JpZHNpemUsIGN1cnJfYXJlYSwgbWluX2FyZWEsIHNvbG4pKQoJCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWlmIChwb2ludHNbbl0ueCA9PSBtYXhfaSAtIDEpCgkJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCX0KCQkJZWxzZQoJCQl7CgkJCQlpZiAoeDIgPiAteTIpCgkJCQl7CgkJCQkJZm9yIChpbnQgaSA9IG1heF9pIC0gMTsgaSA+IG1pbl9pIC0gMTsgaS0tKQoJCQkJCXsKCQkJCQkJZm9yIChpbnQgaiA9IG1pbl9qOyBqIDwgbWF4X2o7IGorKykKCQkJCQkJewoJCQkJCQkJcG9pbnRzW25dLnggPSBpOwoJCQkJCQkJcG9pbnRzW25dLnkgPSBqOwoKCQkJCQkJCWlmICghY3JlYXRlX3BvbHlnb25faml0KHBvaW50cywgbiArIDEsIHRhcmdldF9uLCBncmlkc2l6ZSwgY3Vycl9hcmVhLCBtaW5fYXJlYSwgc29sbikpCgkJCQkJCQkJYnJlYWs7CgkJCQkJCX0KCQkJCQkJaWYgKHBvaW50c1tuXS55ID09IG1pbl9qKQoJCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCWZvciAoaW50IGkgPSBtaW5faTsgaSA8IG1heF9pOyBpKyspCgkJCQkJewoJCQkJCQlmb3IgKGludCBqID0gbWluX2o7IGogPCBtYXhfajsgaisrKQoJCQkJCQl7CgkJCQkJCQlwb2ludHNbbl0ueCA9IGk7CgkJCQkJCQlwb2ludHNbbl0ueSA9IGo7CgkJCQkJCQk7CgkJCQkJCQlpZiAoIWNyZWF0ZV9wb2x5Z29uX2ppdChwb2ludHMsIG4gKyAxLCB0YXJnZXRfbiwgZ3JpZHNpemUsIGN1cnJfYXJlYSwgbWluX2FyZWEsIHNvbG4pKQoJCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWlmIChwb2ludHNbbl0ueSA9PSBtaW5faikKCQkJCQkJCWJyZWFrOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQllbHNlCgkJewoJCQlpZiAoeTIgPiAwKQoJCQl7CgkJCQlpZiAoLXgyID4geTIpCgkJCQl7CgkJCQkJZm9yIChpbnQgaSA9IG1pbl9pOyBpIDwgbWF4X2k7IGkrKykKCQkJCQl7CgkJCQkJCWZvciAoaW50IGogPSBtYXhfaiAtIDE7IGogPiBtaW5faiAtIDE7IGotLSkKCQkJCQkJewoJCQkJCQkJcG9pbnRzW25dLnggPSBpOwoJCQkJCQkJcG9pbnRzW25dLnkgPSBqOwoKCQkJCQkJCWlmICghY3JlYXRlX3BvbHlnb25faml0KHBvaW50cywgbiArIDEsIHRhcmdldF9uLCBncmlkc2l6ZSwgY3Vycl9hcmVhLCBtaW5fYXJlYSwgc29sbikpCgkJCQkJCQkJYnJlYWs7CgkJCQkJCX0KCQkJCQkJaWYgKHBvaW50c1tuXS55ID09IG1heF9qIC0gMSkKCQkJCQkJCWJyZWFrOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UKCQkJCXsKCQkJCQlmb3IgKGludCBpID0gbWF4X2kgLSAxOyBpID4gbWluX2kgLSAxOyBpLS0pCgkJCQkJewoJCQkJCQlmb3IgKGludCBqID0gbWF4X2ogLSAxOyBqID4gbWluX2ogLSAxOyBqLS0pCgkJCQkJCXsKCQkJCQkJCXBvaW50c1tuXS54ID0gaTsKCQkJCQkJCXBvaW50c1tuXS55ID0gajsKCgkJCQkJCQlpZiAoIWNyZWF0ZV9wb2x5Z29uX2ppdChwb2ludHMsIG4gKyAxLCB0YXJnZXRfbiwgZ3JpZHNpemUsIGN1cnJfYXJlYSwgbWluX2FyZWEsIHNvbG4pKQoJCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWlmIChwb2ludHNbbl0ueSA9PSBtYXhfaiAtIDEpCgkJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCX0KCQkJZWxzZQoJCQl7CgkJCQlpZiAoLXgyID4gLXkyKQoJCQkJewoJCQkJCWZvciAoaW50IGogPSBtYXhfaiAtIDE7IGogPiBtaW5faiAtIDE7IGotLSkKCQkJCQl7CgkJCQkJCWZvciAoaW50IGkgPSBtaW5faTsgaSA8IG1heF9pOyBpKyspCgkJCQkJCXsKCQkJCQkJCXBvaW50c1tuXS54ID0gaTsKCQkJCQkJCXBvaW50c1tuXS55ID0gajsKCgkJCQkJCQlpZiAoIWNyZWF0ZV9wb2x5Z29uX2ppdChwb2ludHMsIG4gKyAxLCB0YXJnZXRfbiwgZ3JpZHNpemUsIGN1cnJfYXJlYSwgbWluX2FyZWEsIHNvbG4pKQoJCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkJCQkJCWlmIChwb2ludHNbbl0ueCA9PSBtaW5faSkKCQkJCQkJCWJyZWFrOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UKCQkJCXsKCQkJCQlmb3IgKGludCBqID0gbWluX2o7IGogPCBtYXhfajsgaisrKQoJCQkJCXsKCQkJCQkJZm9yIChpbnQgaSA9IG1pbl9pOyBpIDwgbWF4X2k7IGkrKykKCQkJCQkJewoJCQkJCQkJcG9pbnRzW25dLnggPSBpOwoJCQkJCQkJcG9pbnRzW25dLnkgPSBqOwoKCQkJCQkJCWlmICghY3JlYXRlX3BvbHlnb25faml0KHBvaW50cywgbiArIDEsIHRhcmdldF9uLCBncmlkc2l6ZSwgY3Vycl9hcmVhLCBtaW5fYXJlYSwgc29sbikpCgkJCQkJCQkJYnJlYWs7CgkJCQkJCX0KCQkJCQkJaWYgKHBvaW50c1tuXS54ID09IG1pbl9pKQoJCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJfQoKCQkJfQoJCX0KCX0KCWVsc2UKCXsKCQlpbnQgbWluX2kgPSBzdGQ6Om1heCgwLCBwb2ludHNbbiAtIDFdLnggLSAzKTsKCQlpbnQgbWF4X2kgPSBzdGQ6Om1pbihncmlkc2l6ZSwgcG9pbnRzW24gLSAxXS54ICsgNCk7CgoJCWludCBtaW5faiA9IHN0ZDo6bWF4KC1ncmlkc2l6ZSAvIDIsIHBvaW50c1tuIC0gMV0ueSAtIDMpOwoJCWludCBtYXhfaiA9IHN0ZDo6bWluKGdyaWRzaXplIC8gMiwgcG9pbnRzW24gLSAxXS55ICsgNCk7CgoJCWZvciAoaW50IGkgPSBtaW5faTsgaSA8IG1heF9pOyBpKyspCgkJewoJCQlmb3IgKGludCBqID0gbWluX2o7IGogPCBtYXhfajsgaisrKQoJCQl7CgkJCQlwb2ludHNbbl0ueCA9IGk7CgkJCQlwb2ludHNbbl0ueSA9IGo7CgkJCQljcmVhdGVfcG9seWdvbl9qaXQocG9pbnRzLCBuICsgMSwgdGFyZ2V0X24sIGdyaWRzaXplLCBjdXJyX2FyZWEsIG1pbl9hcmVhLCBzb2xuKTsKCQkJfQoJCX0KCX0KCXBvaW50c1tuXS54ID0gMDsKCXBvaW50c1tuXS55ID0gMDsKCXJldHVybiB0cnVlOwp9CgppbnQgbWFpbigpIHsKCXVzaW5nIG5hbWVzcGFjZSBzdGQ6OmNocm9ubzsKCWF1dG8gdDEgPSBzdGVhZHlfY2xvY2s6Om5vdygpOwoKCWNvbnN0IGludCBuID0gMTY7CglzdGQ6OmFycmF5PHBvaW50LCBuPiBwb2ludHN7fTsKCglpbnQgZ3JpZFNpemUgPSAxMTsKCWludCBtaW5BcmVhID0gZ3JpZFNpemUgKiBncmlkU2l6ZTsKCQoJc3RkOjphcnJheTxwb2ludCwgbj4gcmVzdWx0OwoJCglmb3IgKHBvaW50JiBwIDogcmVzdWx0KXsKCQlwLnggPSAwOwoJCXAueSA9IDA7Cgl9CgkKCWNyZWF0ZV9wb2x5Z29uX2ppdChwb2ludHMsIDEsIG4sIGdyaWRTaXplLCAwLCBtaW5BcmVhLCByZXN1bHQpOwoKCXN0ZDo6Y291dCA8PCAiUmVzdWx0OiAiOwoJZm9yIChwb2ludCYgcCA6IHJlc3VsdCkKCQlzdGQ6OmNvdXQgPDwgIigiPDwgcC54IDw8ICIsICIgPDwgcC55IDw8ICIpICI7CglzdGQ6OmNvdXQgPDwgIlxuQXJlYTogIiA8PCBtaW5BcmVhIDw8ICJcbiI7CgoJYXV0byB0MiA9IHN0ZWFkeV9jbG9jazo6bm93KCk7CglhdXRvIHRpbWVfc3BhbiA9IGR1cmF0aW9uX2Nhc3Q8ZHVyYXRpb248ZG91YmxlPj4odDIgLSB0MSk7CglzdGQ6OmNvdXQgPDwgIlRpbWU6IiA8PCB0aW1lX3NwYW4uY291bnQoKSA8PCAiIHNlY29uZHMuXG4iOwp9