暴力求调
看了题意后,不难写出如下暴力做法:枚举全排列,然后依次连线,没连一条线和前面线的不同交点个数就是当期新分出的块数。因为是圆环,所以答案减去 1。
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
const double eps = 1e-8;
int n, a[25], ans, cnt;
struct twt {
double x, y;
twt(double a = 0, double b = 0) { x = a, y = b; }
twt operator - (twt b) { return twt(x-b.x, y-b.y); }
twt operator / (double b) { return twt(x/b, y/b); }
twt operator + (twt b) { return twt(x+b.x, y+b.y); }
twt operator * (double b) { return twt(x*b, y*b); }
double operator * (twt b) { return x*b.x + y*b.y; }
double operator ^ (twt b) { return x*b.y - b.x*y; }
double len() { return sqrt(x*x + y*y); }
bool operator == (twt b) {
return fabs(x-b.x) <= eps && fabs(y-b.y) <= eps;
}
bool operator < (twt b) const {
return x < b.x || (x == b.x && y < b.y);
}
twt roa() { return twt(y, -x); }
};
std::vector<twt> s;
struct dwd {
twt a, b;
dwd(twt x = twt(), twt y = twt()) { a = x, b = y; }
} line[25];
twt inter(dwd a, dwd b) {
twt p1 = a.a, v1 = a.b, p2 = b.a, v2 = b.b;
return p2 + (v2-p2) * ((v1-p1)^(p2-p1)) / ((v2-p2)^(v1-p1));
}
int solve() {
int an = 1;
for (int i = 1; i <= n; i++) {
dwd now = dwd(twt(i, 1), twt(a[i], 0));
s.clear();
for (int j = 1; j <= cnt; j++)
if (line[j].b.x > a[i]) s.push_back(inter(now, line[j]));
std::sort(s.begin(), s.end());
s.erase(std::unique(s.begin(), s.end()), s.end());
line[++cnt] = now;
an += s.size() + 1;
}
return an-1;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) a[i] = i;
do {
cnt = 0;
ans = std::max(ans, solve());
} while(std::next_permutation(a+1, a+n+1));
printf("%d", ans);
}
这份代码看上去没有任何的问题,然而在 n=8 时答案是 31, 而不是标程的 33,所以 这题是错题 能告诉我哪里写错了吗。