USACO算法系列四十二——starry

    题目:http://www.nocow.cn/index.php/Translate:USACO/starry

    题目还是比较好理解的,想法也比较简单,但是写起来相当麻烦。我的想法是:

    第一,使用广度遍历的方法,遍历出所有的星座,并记录下他们的路径,边框,高度,宽度。

    第二,对于每一个星座,对他们做归一处理,就是另他们的起点都是从0,0开始的。然后画到一个虚拟的天空上,然后遍历接下来的几个星座,并把他们也画到虚拟天空中,如果两个星座重合,那么这两个星座是同一个星座。

    中间优化,1, 两个星座星星数目不一致,排除。

                   2, 两个星座宽度,高度不一致,排除。

    第三,把星座标记到一个新的天空中,打印出来。

    代码如下:

#include <iostream> #include <fstream> #include <string.h> #define SIZE 101 #define COSIZE 501 #define STAR 161 using namespace std; //星星位置 struct Position { int x; int y; }; struct Constellation { //最上方最左侧的位置 int sx; //开始的x int sy; //开始的y //星座长宽 int w; //宽 int h; //高 //星星的广度路径 Position path[STAR]; int pl; }; ifstream fin("starry.in"); ofstream fout("starry.out"); int w, h; int sky[SIZE][SIZE]; //星座链表 Constellation con[COSIZE]; int cl; //标记 char mark[COSIZE]; //虚拟的天空 int virsky[SIZE][SIZE]; //结果 char result[SIZE][SIZE]; //把星星标记在虚拟的天空下 void setvirsky(int index, int t) { memset(virsky, 0, sizeof(int) * SIZE * SIZE); for (int i =0; i < con[index].pl; i ++) { //星星坐标,并作归一化处理 int px = con[index].path[i].x - con[index].sx; int py = con[index].path[i].y - con[index].sy; //变换 if (t == 0) { virsky[px][py] = 1; } else if(t == 1) { virsky[py][con[index].h - px] = 1; } else if (t == 2) { virsky[con[index].h - px][con[index].w - py] = 1; } else if (t == 3) { virsky[con[index].w - py][px] = 1; } else if(t == 4) { virsky[px][con[index].w - py] = 1; } else if(t == 5) { virsky[py][px] = 1; } else if (t == 6) { virsky[con[index].h- px][py] = 1; } else if (t == 7) { virsky[con[index].w - py][con[index].h - px] = 1; } } } //判断星座是否相同 bool isSameCon(int c1, int c2) { //星星数目不一致 if(con[c1].pl != con[c2].pl) return false; if ((con[c1].w != con[c2].w || con[c1].h != con[c2].h) && (con[c1].w != con[c2].h || con[c1].h != con[c2].w)) { return false; } int same = 0; for (int i=0; i < con[c2].pl; i ++) { int px = con[c2].path[i].x - con[c2].sx; int py = con[c2].path[i].y - con[c2].sy; if (virsky[px][py] == 1) { same ++; }//end if virsky == 1 }//end for i if (same == con[c1].pl) { return true; } else return false; } //广度遍历找出星座 void BFSConstllation( int x, int y) { Position * path = con[cl].path; path[0].x = x; path[0].y = y; sky[x][y] = 2; int pl=1; int sx = SIZE; int sy = SIZE; int ex = -1; int ey = -1; //广度遍历 for (int i=0; i < pl; i ++) { int px = path[i].x; int py = path[i].y; //确定长宽 sx = sx < px ? sx : px; ex = ex < px ? px : ex; sy = sy < py ? sy : py; ey = ey < py ? py : ey; //八个方向 //左上 if (px>0 && py>0 && sky[px-1][py-1] == 1) { path[pl].x = px-1; path[pl].y = py-1; sky[px-1][py-1] = 2; pl ++; } //上 if (px > 0 && sky[px-1][py] == 1) { path[pl].x = px-1; path[pl].y = py; sky[px-1][py] = 2; pl ++; } //右上 if(px>0 && py < w-1 && sky[px-1][py+1] == 1) { path[pl].x = px-1; path[pl].y = py +1; sky[px-1][py+1] = 2; pl ++; } //左 if (py>0 && sky[px][py-1] == 1) { path[pl].x = px; path[pl].y = py -1; sky[px][py-1] = 2; pl ++; } //右 if(py < w-1 && sky[px][py+1] == 1) { path[pl].x = px; path[pl].y = py +1; sky[px][py+1] = 2; pl ++; } //左下 if(px < h-1 && py >0 && sky[px+1][py-1] == 1) { path[pl].x = px + 1; path[pl].y = py -1; sky[px+1][py-1] = 2; pl ++; } //下 if (px < h-1 && sky[px+1][py] == 1) { path[pl].x = px +1; path[pl].y = py; sky[px+1][py] = 2; pl ++; } //右下 if(px < h-1 && py < w-1 && sky[px+1][py+1] == 1) { path[pl].x = px +1; path[pl].y = py +1; sky[px+1][py+1] = 2; pl ++; } } con[cl].pl = pl; con[cl].sx = sx; con[cl].sy = sy; con[cl].h = ex - sx; con[cl].w = ey - sy; cl ++; } //广度遍历出所有的星座 void BFSAllConstellation() { for (int i =0; i < h; i ++) { for (int j=0; j < w; j ++) { if (sky[i][j] == 1) { BFSConstllation(i,j); }//end if sky[i][j] }//end for j }// end for i } void markResult(int index) { for (int i=0; i < con[index].pl; i ++) { int px = con[index].path[i].x; int py = con[index].path[i].y; result[px][py] = mark[index]; } } void print() { for (int i=0; i<h; i ++) { for (int j=0; j< w; j ++) { fout << result[i][j]; } fout << endl; } } int main() { //输入数据 fin >> w >> h; for (int i=0; i < h; i ++) { for (int j=0; j < w; j ++) { char c = '0'; fin >> c; sky[i][j] = c - '0'; }//end for j }//end for i BFSAllConstellation(); memset(mark, '0', sizeof(char) * COSIZE); int c = 'a'; for (int i=0; i < cl; i ++) { if (mark[i] != '0') { continue; }//已经标定过的 else { mark[i] = c; c ++; } for (int j=0; j < 8; j ++) { setvirsky(i, j); for (int k=i+1; k < cl; k ++) { if (mark[k] != '0') { continue; }//已经考虑过 else { if (isSameCon(i, k)) { mark[k] = mark[i]; } }//end else }//end for k }//end for j }//end for i memset(result, '0', sizeof(char) * SIZE * SIZE); for (int i=0; i< cl; i ++) { markResult(i); } print(); return 0; }

    运行结果如下:

Executing... Test 1: TEST OK [0.000 secs, 3744 KB] Test 2: TEST OK [0.000 secs, 3744 KB] Test 3: TEST OK [0.000 secs, 3744 KB] Test 4: TEST OK [0.000 secs, 3744 KB] Test 5: TEST OK [0.011 secs, 3744 KB] All tests OK. YOUR PROGRAM ('starry') WORKED FIRST TIME! That's fantastic -- and a rare thing. Please accept these special automated congratulations.

   一遍AC了。努力的结果没有白费啊!

你可能感兴趣的:(USACO算法系列四十二——starry)