USER: chen chen [thestor1] TASK: starry LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.008 secs, 3508 KB] Test 2: TEST OK [0.008 secs, 3508 KB] Test 3: TEST OK [0.011 secs, 3508 KB] Test 4: TEST OK [0.008 secs, 3508 KB] Test 5: TEST OK [0.016 secs, 3508 KB] All tests OK.Your program ('starry') produced all correct answers! This is your submission #3 for this problem. Congratulations!
这道题我是用的是最直接的方法。用DFS得到每个cluster,然后之前所有的cluster都逐一比较。比较的时候也是8种形状逐一比较。当然,先比较star的个数是否一样,轮廓(长方形)是否一样。每个cluster还用一个set保存了里面所有的点。如果usaco支持unordered_set的话,说不定会更快些。标准答案比较的时候看着像是位操作啥的,应该比我的直观解法快特别多,也没看懂。
/*
ID: thestor1
LANG: C++
TASK: starry
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <climits>
#include <cassert>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
// #include <unordered_map>
// #include <unordered_set>
using namespace std;
const int MAXW = 100;
class Cluster {
public:
char label;
int H, W;
int ll, lr, ul, ur;
int size;
// std::vector<pair<int, int> > ones;
set<int> ones;
Cluster()
{
H = W = ll = lr = ul = ur = -1;
size = 0;
}
};
bool isIn(int r, int c, int H, int W)
{
return 0 <= r && r < H && 0 <= c && c < W;
}
inline int index(int r, int c)
{
return r * MAXW + c;
}
void dfs(int r, int c, int H, int W, vector<std::vector<char> > &skymap, Cluster &cluster)
{
if (cluster.ll < 0 || r < cluster.ll)
{
cluster.ll = r;
}
if (cluster.lr < 0 || c < cluster.lr)
{
cluster.lr = c;
}
if (r > cluster.ul)
{
cluster.ul = r;
}
if (c > cluster.ur)
{
cluster.ur = c;
}
skymap[r][c] = cluster.label;
cluster.size++;
// cluster.ones.push_back(make_pair(r, c));
cluster.ones.insert(index(r, c));
int dx[] = {-1, -1, -1, 0, 1, 1, 1, 0}, dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
for (int d = 0; d < 8; ++d)
{
int nr = r + dx[d], nc = c + dy[d];
if (isIn(nr, nc, H, W) && skymap[nr][nc] == '1')
{
dfs(nr, nc, H, W, skymap, cluster);
}
}
}
bool isSame(const Cluster &c1, Cluster &c2, vector<std::vector<char> > &skymap)
{
if (c1.size != c2.size)
{
return false;
}
if (c1.H == c2.H && c1.W == c2.W)
{
// up->down, left->right
bool flag = true;
for (int i1 = c1.ll, i2 = c2.ll; i1 <= c1.ul && i2 <= c2.ul; ++i1, ++i2)
{
for (int j1 = c1.lr, j2 = c2.lr; j1 <= c1.ur && j2 <= c2.ur; ++j1, ++j2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
// up->down, right->left
flag = true;
for (int i1 = c1.ll, i2 = c2.ll; i1 <= c1.ul && i2 <= c2.ul; ++i1, ++i2)
{
for (int j1 = c1.lr, j2 = c2.ur; j1 <= c1.ur && j2 >= c2.lr; ++j1, --j2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
// down->up, left->right
flag = true;
for (int i1 = c1.ll, i2 = c2.ul; i1 <= c1.ul && i2 >= c2.ll; ++i1, --i2)
{
for (int j1 = c1.lr, j2 = c2.lr; j1 <= c1.ur && j2 <= c2.ur; ++j1, ++j2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
// down->up, right->left
flag = true;
for (int i1 = c1.ll, i2 = c2.ul; i1 <= c1.ul && i2 >= c2.ll; ++i1, --i2)
{
for (int j1 = c1.lr, j2 = c2.ur; j1 <= c1.ur && j2 >= c2.lr; ++j1, --j2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
}
if (c1.H == c2.W && c1.W == c2.H)
{
// left->right, down->up
bool flag = true;
for (int i1 = c1.ll, j2 = c2.lr; i1 <= c1.ul && j2 <= c2.ur; ++i1, ++j2)
{
for (int j1 = c1.lr, i2 = c2.ul; j1 <= c1.ur && i2 >= c2.ll; ++j1, --i2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
// right->left, down->up
flag = true;
for (int i1 = c1.ll, j2 = c2.ur; i1 <= c1.ul && j2 >= c2.lr; ++i1, --j2)
{
for (int j1 = c1.lr, i2 = c2.ul; j1 <= c1.ur && i2 >= c2.ll; ++j1, --i2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
// left->right, up->down
flag = true;
for (int i1 = c1.ll, j2 = c2.lr; i1 <= c1.ul && j2 <= c2.ur; ++i1, ++j2)
{
for (int j1 = c1.lr, i2 = c2.ll; j1 <= c1.ur && i2 <= c2.ul; ++j1, ++i2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
// right->left, up->down
flag = true;
for (int i1 = c1.ll, j2 = c2.ur; i1 <= c1.ul && j2 >= c2.lr; ++i1, --j2)
{
for (int j1 = c1.lr, i2 = c2.ll; j1 <= c1.ur && i2 <= c2.ul; ++j1, ++i2)
{
if (c1.ones.count(index(i1, j1)) != c2.ones.count(index(i2, j2)))
{
flag = false;
break;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return true;
}
}
return false;
}
void repaint(vector<std::vector<char> > &skymap, char label, Cluster &cluster)
{
for (int r = cluster.ll; r <= cluster.ul; ++r)
{
for (int c = cluster.lr; c <= cluster.ur; ++c)
{
if (skymap[r][c] == label)
{
skymap[r][c] = cluster.label;
}
}
}
}
int main()
{
ifstream fin("starry.in");
ofstream fout("starry.out");
int W, H;
fin>>W>>H;
std::vector<std::vector<char> > skymap(H, std::vector<char>(W, '0'));
std::vector<Cluster> clusters;
for (int r = 0; r < H; ++r)
{
string row;
fin>>row;
for (int c = 0; c < W; ++c)
{
if (row[c] == '1')
{
skymap[r][c] = '1';
}
}
}
char label = 'a';
for (int r = 0; r < H; ++r)
{
for (int c = 0; c < W; ++c)
{
if (skymap[r][c] == '1')
{
Cluster cluster;
cluster.label = label;
dfs(r, c, H, W, skymap, cluster);
// sort(cluster.ones.begin(), cluster.ones.end());
cluster.H = cluster.ul - cluster.ll + 1;
cluster.W = cluster.ur - cluster.lr + 1;
bool unique = true;
for (int i = 0; i < clusters.size(); ++i)
{
if (isSame(clusters[i], cluster, skymap))
{
unique = false;
cluster.label = clusters[i].label;
repaint(skymap, label, cluster);
break;
}
}
if (unique)
{
// cluster.label = label;
clusters.push_back(cluster);
// paint(skymap, cluster);
label++;
}
}
}
}
for (int r = 0; r < H; ++r)
{
for (int c = 0; c < W; ++c)
{
fout<<skymap[r][c];
}
fout<<endl;
}
fin.close();
fout.close();
return 0;
}