构造 ZOJ 3810 A Volcanic Island

来源:互联网 发布:js window document 编辑:程序博客网 时间:2024/04/28 00:43

A Volcanic Island

Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge

An underwater volcano has erupted massively in somewhere of the deep Atlantis Ocean. This large eruption led to the birth of a new volcanic island, which had a shape of square. Near the island, there are N countries. All of them have claimed the sovereignty over the island.

After a lot of multilateral negotiation and occasional armed conflicts, the N countries decided to divide the square volcanic island equally. They partitioned the island into N x N small equal-sized square chunks. Each country could get a connected region consists of exact N chunks.

Two chunks A and B are called "connected" if they share an edge, or there exists another chunk C connected with both A and B. A group of chunks are called "connected region" if any two of these chunks are connected.

Every country want a unique region. It means the N regions should be different with each other. Two regions are considered as the same if and only if one can transform into the other by an isometry (a combination of rigid motions, including translation, rotation and reflection).

In a nutshell, your task is to divide a square island with N x N chunks into N connected regions with different shape. You also need to draw a map to color the regions of the map so that no two edge-adjacent regions have the same color. Most of the people in these countries believed that four different colors are enough. So you can mark these regions with at most four colors, red, green, blue and yellow.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There is only an integer N (1 <= N <= 100).

Output

For each test case, output a valid map described above. If there is no solution, output "No solution!" instead. Please note that only four colors ('R', 'G', 'B' and 'Y') can be used to drawing the map.

Sample Input

225

Sample Output

No solution!YYYGRYGGGRYGYYRBYYYRBBBBR

Author: ZHOU, Yuchen
Source: The 2014 ACM-ICPC Asia Mudanjiang Regional First Round


题意:有一个N*N的方格图,每个格子要涂上四种颜色中的一种,如果相邻的颜色相同,他们是同一个区域,现在需要输出一个N*N的方格图,方格图中的所有区域的形状两两不相同,如果翻转和旋转后相同当做是相同的。


思路:一看就知道是构造,但是智商真的是捉急啊,想不到什么好的构造办法,构造题一般是要以一两种特定的方式进行逐步的求解吧。。。感觉是这样,一开始乱来,想着会不会沿着外围走就行了呢?可惜是不行的,后来想到了一个构造方法,就是不断摆出"Z"行,但是发现只能摆n/2个,于是又没想下去了,其实这里已经比较接近答案了。最后还是看了题解才知道....Orz 

一个可能的构造形式如下:

10 * 10的时候

BBBBBBBBBY
GGGGGGGGBY
BBBBBBBGGY
GGGGGGBBBY
BBBBBGGGGY
YYYYBBBBBY
BBBYGGGGGY
YYBYYYYYGY
YYBBBBBBGY
YYYYYYGGGY 


于是要特判一些n比较小的情况,就行了....

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cassert>#include <queue>#include <vector>#include <map>#include <set>#include <algorithm>using namespace std;#define rep(i,a,b) for(int i=(a);i<(int)(b);++i)#define rrep(i,b,a) for(int i=(b);i>=(int)(a);--i)#define eps 1e-9#define clr(a,x) memset(a,x,sizeof(a))#define LL long longconst int maxn = 200+5;const int Move[2][4] = { {1,0,-1,0},{0,1,0,-1} };char col[] = "YBGR";char ans[maxn][maxn];char color[maxn];bool adj[maxn][maxn];int n;/*形式如下BBBBBBBBBYGGGGGGGGBYBBBBBBBGGYGGGGGGBBBYBBBBBGGGGYYYYYBBBBBYBBBYGGGGGYYYBYYYYYGYYYBBBBBBGYYYYYYYGGGY */bool inRange(int r,int c) { return 0<=r&&r<n&&0<=c&&c<n; }bool vis[maxn][4];int rst[maxn];int S[maxn*maxn],c;bool build_color(int rest){    if (rest == 0) return true;    int k = -1;    for(int i = 1; i <= n; ++i)    if(color[i]==0 && (k == -1 || rst[i] < rst[k])) k = i;    if (rst[k] == 0) return false;    rep(i,0,4) {        if (vis[k][i]) continue;        vis[k][i] = true;        color[k] = col[i];        int cc = c;        rep(j,1,n+1)        if (adj[k][j] && !vis[j][i]) {            vis[j][i] = true;            --rst[j];            S[c++] = j << 2 | i;        }        if (build_color(rest-1)) return true;        vis[k][i] = false;        while (c > cc) {            int x = S[--c];            vis[x>>2][x&3] = false;            ++rst[x>>2];        }    }    color[k] = 0;    return false;}void out(){    puts("");    rep(i,0,n) {        rep(j,0,n) printf("%c",ans[i][j]+'0');        puts("");    }    puts("");}bool solve(){    if (n == 2 || n == 3 || n == 4) return false;    else if(n == 1) { puts("Y"); return true; }    else if(n == 6) {        puts("YYYYYY");        puts("BBBRRB");        puts("BBBRRB");        puts("RYRRYB");        puts("RYYYYB");        puts("RRRRBB");        return true;    } else if (n == 5) {        puts("YYYGR");        puts("YGGGR");        puts("YGYYR");        puts("BYYYR");        puts("BBBBR");        return true;    }    clr(ans,0);    int cnt = 1;    rep(i,0,n) rep(j,0,n) ans[i][j] = cnt;    ++cnt;    rep(i,0,n) ans[i][n-1] = cnt;    ++cnt;    rep(i,0,n/2) {        rep(j,0,n-1-i) ans[i][j] = cnt;        rep(j,n-2-i,n-1) ans[i+1][j] = cnt;        ++cnt;    }    rep(i,n/2,n) {        if (i+2>n-2) break;        rep(j,0,n-1-i) ans[i][j] = cnt;        ans[i+1][n-2-i] = cnt;        rep(j,n-2-i,n-2) ans[i+2][j] = cnt;        ++cnt;    }    int len = 0;    rep(j,n-1-n/2,n-1) {        ans[n/2+1][j] = cnt; ++len;    }    rep(i,n/2+2,n) ans[i][n-2] = cnt, ++len;    rrep(j,n-3,0) {        if(len == n) break;        ans[n-1][j] = cnt;        ++len;    }//    out();    clr(adj,0);    rep(i,0,n) rep(j,0,n) rep(k,0,4) {        int rr = i + Move[0][k];        int cc = j + Move[1][k];        if(!inRange(rr,cc)) continue;        int u = ans[i][j],v=ans[rr][cc];        if (u == v) continue;        adj[u][v] = adj[v][u] = true;    }    rep(i,1,n+1) rst[i] = 4;    clr(vis,0); c = 0; clr(color,0);    build_color(n);    rep(i,0,n) rep(j,0,n) {     //   x = max((int)ans[i][j],x);        assert(ans[i][j]<maxn);        ans[i][j] = color[ans[i][j]];    }    rep(i,0,n)    printf("%s\n",ans[i]);    return true;}int main(){    int T; cin >> T;    while (T--) {        scanf("%d",&n);        if (!solve()) puts("No solution!");    }}


0 0
原创粉丝点击