题意
数据范围
(0 leq W,H leq 100),
(0 leq 星群数量 leq 500),
(0 leq 不相似星群数量 leq 26),
(1 leq 星群中星星的数量 leq 160)
思路
这个的关键主要是找到判定两个星群相似的方法。
下面有一个定理:若一个星群中所有点两两距离的和,与另一个星群相等,那么这两个星群相似。
这里给出一个直观的证明:将星群视为一个多边形,这些距离将多边形划分为一个个三角形,两个多边形划分的所有三角形全等,那个两个多边形相似。
下面证明两个多边形对应三角形全等:因为距离和相等,并且一格的长度是1,因此对应三角形的对应边都是相等的。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef pair<int, int> pii;
const int N = 110, M = N * N;
const double eps = 1e-6;
int n, m;
char g[N][N];
pii point[M];
int cnt;
bool st[N][N];
double hash_val[M];
int num;
int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
double get_dist(pii a, pii b)
{
double dx = a.first - b.first;
double dy = a.second - b.second;
return sqrt(dx * dx + dy * dy);
}
double get_hash()
{
double res = 0;
for(int i = 0; i < cnt; i ++) {
for(int j = i + 1; j < cnt; j ++) {
res += get_dist(point[i], point[j]);
}
}
return res;
}
char get_id(double hash)
{
for(int i = 0; i < num; i ++) {
if(fabs(hash_val[i] - hash) < eps) {
return i + 'a';
}
}
hash_val[num] = hash;
num ++;
return num - 1 + 'a';
}
void bfs(int ax, int ay)
{
cnt = 0;
queue<pii> que;
que.push({ax, ay});
st[ax][ay] = true;
point[cnt] = {ax, ay};
cnt ++;
while(que.size()) {
auto t = que.front();
que.pop();
int tx = t.first, ty = t.second;
for(int i = 0; i < 8; i ++) {
int x = tx + dx[i], y = ty + dy[i];
if(st[x][y]) continue;
if(x < 1 || x > n || y < 1 || y > m) continue;
if(g[x][y] != '1') continue;
que.push({x, y});
st[x][y] = true;
point[cnt] = {x, y};
cnt ++;
}
}
}
int main()
{
scanf("%d%d", &m, &n);
for(int i = 1; i <= n; i ++) scanf("%s", g[i] + 1);
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
if(g[i][j] == '1') {
bfs(i, j);
double hash = get_hash();
char ch = get_id(hash);
for(int k = 0; k < cnt; k ++) {
int x = point[k].first, y = point[k].second;
g[x][y] = ch;
}
}
}
}
for(int i = 1; i <= n; i ++) printf("%s
", g[i] + 1);
return 0;
}