KC看星(star) \operatorname{KC看星(star)} KC看星(star)
题目链接: SSL比赛 1496 \operatorname{SSL比赛\ 1496} SSL比赛 1496
题目
“一闪一闪亮晶晶,满天都是小星星”
Kc 吟唱着歌谣,躺在草坪上边想着她边看起了星星。 Kc 刚刚结识了笛卡尔这位好基友,认为他的坐标系非常神奇。于是他随机地选出了 8 8 8 颗星星,并且给它们标上了坐标。 Kc 又不甘寂寞,于是思考起一个问题:这八个点能否恰好构成一个正方形和一个矩形呢?
输入
输入文件包括 1 1 1 行 16 16 16 个数,表示 8 8 8 个星星的坐标,坐标绝对值不超过 10000 10000 10000 。
输出
输出文件第一行是 “YES” 或者 “NO” 。表示是否有解。
若有解则第二行依次输出正方形每个顶点的序号。第三行依次输出矩形每个顶点的序号。序号即为输入的顺序。
另外注意:因为 kc 是一个刁端的人,所以他要求第二行和第三行这八个数要字典序最小。
四点共线不能认为是正方形或矩形
样例输入
0 0 10 11 10 0 0 11 1 1 2 2 2 1 1 2
样例输出
YES
5 6 7 8
1 2 3 4
思路
这道题就直接暴力。
就枚举全排列,然后看能不能前 4 4 4 个点组成正方形,后面选的 4 4 4 个点组成矩形。
至于怎么判断是不是,就通过性质:
- 四条边相等,对角线相等的图形是正方形
- 对边相等,对角线相等的图形是矩形
就判断满不满足这两个性质,来判断是不是正方形和矩形。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int x[11], y[11], dis[11][11], a[11];
bool yes, in[11];
void check() {
if (dis[a[1]][a[2]] == dis[a[1]][a[4]] && dis[a[1]][a[2]] == dis[a[2]][a[3]] && dis[a[2]][a[3]] == dis[a[3]][a[4]])//正方形四条边相等
if (dis[a[1]][a[3]] == dis[a[2]][a[4]])//正方形对角线相等
if (dis[a[5]][a[6]] == dis[a[7]][a[8]] && dis[a[5]][a[8]] == dis[a[6]][a[7]])//矩形对边相等
if (dis[a[5]][a[7]] == dis[a[6]][a[8]]) {//矩形对角线相等
yes = 1;//标记找到答案
sort(a + 1, a + 4 + 1);//按字典序排序
sort(a + 5 + 1, a + 8 + 1);
printf("YES\n");//输出
for (int i = 1; i <= 4; i++)
printf("%d ", a[i]);
printf("\n");
for (int i = 5; i <= 8; i++)
printf("%d ", a[i]);
return ;
}
}
void dfs(int len) {
if (yes) return ;//已经找到一个可行的
if (len > 8) {//找到一种排列
check();
return ;
}
for (int i = 1; i <= 8; i++)//枚举下一个数可以是什么
if (!in[i]) {
in[i] = 1;
a[len] = i;
dfs(len + 1);
in[i] = 0;
}
}
int main() {
for (int i = 1; i <= 8; i++)
scanf("%d %d", &x[i], &y[i]);//读入
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
if (i != j)//预处理两点的位置
dis[i][j] = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
dfs(1);//暴力全排列
if (!yes) printf("NO");//没有方案输出
return 0;
}
2281

被折叠的 条评论
为什么被折叠?



