USACO 5.1 Starry Night

这个题我直接模拟的,具体做法是:

找到每种图案所在的最小矩形块,把占得长和宽记录一下。然后以最小矩形块的左下角为原点,将团中的坐标重构并排序存储。然后不同图案直接对比,然后标号就行了。注意对比的时候需要考虑4种旋转,还有反转。总共8种情况。。。又写了160来行,160行已然无压力了。。。样例过了一般就过了吧。。。贴下挫代码:

/*
ID: zlqest11
LANG: C++
TASK: starry
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const short N = 105;

int m, n, ct;
char str[N][N];
int lab[N][N];
int totind, ind[505];
struct node{
int x, y;
node(){}
node(int a, int b){
x = a, y = b;
}
};
struct cluster{
int h, w;
vector <node> loc;
}pic[505];

bool cmp(const node &a, const node &b){
if(a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}

void floodfill(int x, int y, int ct){
queue <node> q;
node u;
int tx, ty;
lab[x][y] = ct;
q.push(node(x,y));
while(!q.empty()){
u = q.front();
pic[ct].loc.push_back(node(u.x, u.y));
q.pop();
for(int px = -1; px <= 1; px++)
for(int py = -1; py <= 1; py++){
tx = u.x + px;
ty = u.y + py;
if(tx<0 || tx>=n || ty<0 || ty>=m) continue;
if(lab[tx][ty]==-1 && str[tx][ty]=='1'){
lab[tx][ty] = ct;
q.push(node(tx, ty));
}
}
}
int len = pic[ct].loc.size();
int lx, ly, rx, ry;
sort(pic[ct].loc.begin(), pic[ct].loc.end(), cmp);
lx = ly = 150;
rx = ry = -1;
for(int i = 0; i < len; i++){
lx = min(lx, pic[ct].loc[i].x);
ly = min(ly, pic[ct].loc[i].y);
rx = max(rx, pic[ct].loc[i].x);
ry = max(ry, pic[ct].loc[i].y);
}
for(int i = 0; i < len; i++){
pic[ct].loc[i].x -= lx-1;
pic[ct].loc[i].y -= ly-1;
}
pic[ct].h = rx-lx+1;
pic[ct].w = ry-ly+1;
}

void roll(int pos){
node tmp;
int len = pic[pos].loc.size();
for(int i = 0; i < len; i++){
tmp.y = pic[pos].h-pic[pos].loc[i].x+1;
tmp.x = pic[pos].loc[i].y;
pic[pos].loc[i] = tmp;
}
swap(pic[pos].h, pic[pos].w);
sort(pic[pos].loc.begin(), pic[pos].loc.end(), cmp);
}

void flip(int pos){
int len = pic[pos].loc.size();
for(int i = 0; i < len; i++)
pic[pos].loc[i].x = pic[pos].h-pic[pos].loc[i].x+1;
sort(pic[pos].loc.begin(), pic[pos].loc.end(), cmp);
}

bool isSame(int a, int b){
int i, len = pic[a].loc.size();
for(i = 0; i < 4; i++){
roll(b);
bool flag = true;
if(pic[b].h!=pic[a].h || pic[b].w!=pic[a].w)
flag = false;
if(pic[b].loc.size() != pic[a].loc.size())
flag = false;
for(int j = 0; j < len; j++){
if(pic[a].loc[j].x!=pic[b].loc[j].x || pic[a].loc[j].y!=pic[b].loc[j].y){
flag = false;
break;
}
}
if(flag) return true;
}
return false;
}

int main()
{
freopen("starry.in", "r", stdin);
freopen("starry.out", "w", stdout);
scanf("%d%d", &m, &n);
for(int i = 0; i < n; i++)
scanf(" %s", str[i]);
memset(lab, -1, sizeof(lab));
for(int i = ct = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(lab[i][j]==-1 && str[i][j]=='1'){
floodfill(i, j, ct);
++ct;
}
memset(ind, -1, sizeof(ind));
totind = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(ind[lab[i][j]]==-1 && str[i][j]=='1'){
ind[lab[i][j]] = ++totind;
for(int k = 0; k < ct; k++){
if(isSame(lab[i][j], k)){
ind[k] = totind;
}
if(ind[k] != totind){
flip(k);
if(isSame(lab[i][j], k)){
ind[k] = totind;
}
}
}
}
}
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(lab[i][j]!=-1 && str[i][j]=='1'){
str[i][j] = 'a'+ind[lab[i][j]]-1;
}
}
for(int i = 0; i < n; i++)
printf("%s\n", str[i]);
return 0;
}



你可能感兴趣的:(USACO)