#include #include #include #include #include #define FOR(a,b,c) for(int a=b;a<=c;a++) #define REP(a,c) for(int a=0;a=c;a--) #define WT while(1) #define GETI(a) scanf("%d", &a) #define BZ(a) memset(a,0,sizeof(a)) #define FILL(a,b) fill(a,a+(sizeof(a)/sizeof(a[0])),b) #define FOREACH(a,b) for(__typeof((b).begin()) a=(b).begin(); a!=(b).end();a++) #define D(args...) //printf(args) using namespace std; struct cell { int id; char c; int nbrs[10]; int nn; void linkto(int i) { nbrs[nn]=i; ++nn; } int dist; }; cell cells[50*50]; cell *grid[50][50]; int H; int NP; int pointpoint[1500][1500]; int pointclass[1500][4]; int classclass[4][4]; #include int width(int y) { int W =H; if(y < H) W += y; else W += 2*H-2-y; return W; } int dmatrix[6][6]; int NV; int setn[6]; int find_set(int i) { return setn[i]; } void union_set(int a, int b) { REP(i, NV) if(setn[i]==b) setn[i]=a; } struct edge { int a,b,c; bool operator<(const edge & other) const { return c < other.c; } }; int mst() { REP(i, NV) setn[i]=i; edge edges[36]; int ne=0; REP(i, NV) REP(j, i) { edge E = { i, j, dmatrix[i][j] }; edges[ne++]=E; } sort(edges, edges+ne); int cost=0; int done=0; REP(i, ne) { int q = find_set(edges[i].a); int w = find_set(edges[i].b); if(q != w) { D("EDGE %d %d %d\n", edges[i].a, edges[i].b, edges[i].c); cost+=edges[i].c; union_set(q,w); done++; if(done == NV-1) break; } } return cost; } int main() { WT { GETI(H); if(!H) break; int id=0; REP(i, 2*H-1) { int W = width(i); D("row %d W %d\n", i, W); REP(j, W) { char s[20]; scanf("%s", s); cell &C = cells[id]; grid[i][j] = &C; C.id = id; C.c = s[0]; C.nn = 0; ++id; } } NP=id; FOR(i, 0, 2*H-2) { int W = width(i); REP(j, W) { cell &C = *grid[i][j]; if(j > 0) { // left C.linkto(grid[i][j-1]->id); } if(j+1 < W) { // right C.linkto(grid[i][j+1]->id); } } } FOR(i, 0, H-1) { int W = width(i); REP(j, W) { cell &C = *grid[i][j]; if(j > 0 && i > 0) { // upleft C.linkto(grid[i-1][j-1]->id); } if(j+1 < W && i>0) { // upright C.linkto(grid[i-1][j]->id); } } } FOR(i, H, 2*H-2) { int W = width(i); REP(j, W) { cell &C = *grid[i][j]; // upleft C.linkto(grid[i-1][j]->id); // upright C.linkto(grid[i-1][j+1]->id); } } FOR(i, 0, H-2) { int W = width(i); REP(j, W) { cell &C = *grid[i][j]; // downleft C.linkto(grid[i+1][j]->id); // downright C.linkto(grid[i+1][j+1]->id); } } FOR(i, H-1, 2*H-3) { int W = width(i); REP(j, W) { cell &C = *grid[i][j]; if(j>0) { // downleft C.linkto(grid[i+1][j-1]->id); } if(j+1id); } } } int n=0; REP(i, 2*H-1) { int W = width(i); REP(q, 2*H-W) D(" "); REP(j, W) { D(" %02d", grid[i][j]->id); ++n; } D("\n"); } REP(c1, 4) REP(c2, 4) classclass[c1][c2]=1000; REP(cl, 4) { REP(i, NP) cells[i].dist = -1; deque que; REP(i, NP) { if(cells[i].c == 'A' + cl) { que.push_back(i); cells[i].dist = 0; } } while(!que.empty()) { int cnum = que.front(); que.pop_front(); cell & C = cells[cnum]; REP(q, C.nn) { int nnum = C.nbrs[q]; if(cells[nnum].dist < 0) { cells[nnum].dist = C.dist+1; que.push_back(nnum); } } } REP(i, NP) { pointclass[i][cl] = cells[i].dist; if(cells[i].c>='A' && cells[i].c<='D') { int c2 = cells[i].c-'A'; classclass[cl][c2] = min(classclass[cl][c2], cells[i].dist); classclass[c2][cl] = min(classclass[c2][cl], cells[i].dist); } } } REP(CLASS, 4) { D("-- to %d\n", CLASS); REP(i, 2*H-1) { int W = width(i); REP(q, 2*H-W) D(" "); REP(j, W) { D(" %02d", pointclass[grid[i][j]->id][CLASS]); ++n; } D("\n"); } } REP(z, NP) { REP(i, NP) cells[i].dist = -1; deque que; cells[z].dist=0; que.push_back(z); while(!que.empty()) { int cnum = que.front(); que.pop_front(); cell & C = cells[cnum]; pointpoint[z][cnum] = cells[cnum].dist; REP(q, C.nn) { int nnum = C.nbrs[q]; if(cells[nnum].dist < 0) { cells[nnum].dist = C.dist+1; que.push_back(nnum); } } } } REP(i,4) REP(j,4) if(i!=j) { classclass[i][j]--; D("CLASSCLASS %d %d %d\n", i, j, classclass[i][j]); } REP(i,4) REP(j,NP) pointclass[j][i]--; REP(i, NP) REP(j, NP) pointpoint[i][j]--; // 1. class-only NV=4; REP(i, 4) REP(j, 4) dmatrix[i][j] = classclass[i][j]; int result = mst(); D("class-only %d\n", result); // 2. 1 point extra NV=5; REP(p, NP) { REP(i, 4) { dmatrix[i][4] = pointclass[p][i]; dmatrix[4][i] = pointclass[p][i]; } if(p==18) { REP(q, 6) { REP(w, 6) D(" %d", dmatrix[w][q]); D("\n"); } } int r=mst()+1; D("with point %d: %d\n", p, r); result = min(result, r); } // 3. 2 points extra NV=6; REP(p, NP) { REP(q, NP) { REP(i, 4) { dmatrix[i][4] = pointclass[p][i]; dmatrix[4][i] = pointclass[p][i]; dmatrix[i][5] = pointclass[q][i]; dmatrix[5][i] = pointclass[q][i]; } dmatrix[5][4] = dmatrix[4][5] = pointpoint[p][q]; int r = mst()+2; D("with points %d & %d: %d\n", p, q, r); result = min(result, r); } } printf("You have to buy %d parcels.\n", result); } return 0; }