USACO starry

  这个题就是图像识别类型的模拟题, 我们可以先将每个图像所在的矩形求出来然后在进行比对,实现的时候我们对每个图形进行染色, 记录染色的区域, 在统计一下染色的数目, 那个两个图像相同的充分必要条件就是a的数目等于b的数目,a染色的区域b也染色。代码如下:

/*
    ID: m1500293
    LANG: C++
    PROG: starry
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
int H, W;
char Map[110][110];
struct Mat
{
    int x1, y1, x2, y2;
    int num;               //联通块的数量
}mat[550];
int nmat;
void update(int x, int y)
{
    if(!mat[nmat].x1 || mat[nmat].x1>x) mat[nmat].x1 = x;
    if(!mat[nmat].y1 || mat[nmat].y1>y) mat[nmat].y1 = y;
    if(!mat[nmat].x2 || mat[nmat].x2<x) mat[nmat].x2 = x;
    if(!mat[nmat].y2 || mat[nmat].y2<y) mat[nmat].y2 = y;
}

//bool vis[110][110];
int col[110][110];
struct P{ int x, y; };
bool inside(int x, int y) { return (x>=1&&x<=H&&y>=1&&y<=W); }
int flood(int x, int y, int co)
{
    int dx[] = {-1, 0, 1, 0, -1, -1, 1, 1};
    int dy[] = {0, -1, 0, 1, 1, -1, -1, 1};
    int num = 1;
    //vis[x][y] = 1;
    col[x][y] = co;
    update(x, y);
    queue<P> que;
    que.push((P){x, y});
    while(!que.empty())
    {
        P u = que.front(); que.pop();
        for(int i=0; i<8; i++)
        {
            int nx = u.x+dx[i], ny = u.y + dy[i];
            if(inside(nx, ny) && col[nx][ny]==-1 && Map[nx][ny]=='1')
            {
                que.push((P){nx, ny});
                num++;
                update(nx, ny);
                col[nx][ny] = co;
            }
        }
    }
    return num;
}

char res[110][110], p[550];

void rot(char a[][110], int lx, int ly)  //顺时针旋转90
{
    char tp[110][110];
    for(int i=0; i<lx; i++)
        for(int j=0; j<ly; j++)
            tp[j][lx-i-1] = a[i][j];
    for(int i=0; i<ly; i++)
        for(int j=0; j<lx; j++)
        a[i][j] = tp[i][j];
}

void turn(char a[][110], int lx, int ly)
{
    for(int i=0; i<lx; i++)
        for(int j=0; j<ly/2; j++)
            swap(a[i][j], a[i][ly-1-j]);
}

bool ok(int aa, char a[][110], int lx, int ly)
{
    for(int i=0; i<lx; i++)
        for(int j=0; j<ly; j++)
        {
            int ox = mat[aa].x1+i, oy = mat[aa].y1+j;
            if(col[ox][oy]==aa && a[i][j]=='0') return false;
        }
    return true;
}

bool same(int a, int b)
{
    if(mat[a].num != mat[b].num) return false;
    char temp[110][110];
    int ax = mat[a].x2-mat[a].x1+1, ay = mat[a].y2-mat[a].y1+1;
    int lx = mat[b].x2-mat[b].x1+1, ly = mat[b].y2-mat[b].y1+1;
    for(int i=0; i<lx; i++)
        for(int j=0; j<ly; j++)
        {
            int ox = i+mat[b].x1, oy = j+mat[b].y1;
            temp[i][j] = Map[ox][oy];
        }
    if(ax==lx && ay==ly && ok(a, temp, lx, ly)) return true;
    for(int i=0; i<4; i++)
    {
        rot(temp, lx, ly); swap(lx, ly);
        if(ax==lx && ay==ly && ok(a, temp, lx, ly)) return true;
    }
    turn(temp, lx, ly);
    for(int i=0; i<4; i++)
    {
        rot(temp, lx, ly); swap(lx, ly);
        if(ax==lx && ay==ly && ok(a, temp, lx, ly)) return true;
    }
    return false;
}

int main()
{
    freopen("starry.in", "r", stdin);
    freopen("starry.out", "w", stdout);
    scanf("%d%d", &W, &H);
    for(int i=1; i<=H; i++)
        scanf("%s", Map[i]+1);
    nmat = 0;
    memset(col, -1, sizeof(col));
    for(int i=1; i<=H; i++)
        for(int j=1; j<=W; j++)
            if(Map[i][j]=='1' && col[i][j]==-1)
            {
                int n = flood(i, j, nmat);
                mat[nmat].num = n;
                nmat++;
            }
    memcpy(res, Map, sizeof(Map));
    char c = 'a';
    for(int i=0; i<nmat; i++)
    {
        int idx = -1;
        for(int j=0; j<i; j++)
            if(same(i, j))
            {
                idx = j;
                break;
            }
        if(idx != -1)  p[i] = p[idx];
        else p[i] = c++;
        for(int ii=mat[i].x1; ii<=mat[i].x2; ii++)
            for(int j=mat[i].y1; j<=mat[i].y2; j++)
                if(col[ii][j]==i) res[ii][j] = p[i];
    }
    for(int i=1; i<=H; i++)
    {
        for(int j=1; j<=W; j++)
            printf("%c", res[i][j]);
        printf("\n");
    }
    return 0;
}

 

你可能感兴趣的:(USACO starry)