3279:Fliptile
keyword
BruteForce C++
概要
ボード(15*15以下)が与えられて、各セルは黒か白である。あるセルを選ぶとそのセル及び隣接するセルがフリップする。フリップの回数が最小のものを出力せよ。最小回数のものが複数あるときは辞書順最小のものを答えよ。
よくある問題。一番左の列を決めれば後は決まるので左の列に関してBruteForceすればよい。問題は辞書順最小。vector
bool board[20][20]; bool flipped[20][20]; int h, w; int dx[] = {0,1,0,-1,0}, dy[] = {0,0,1,0,-1}; int main(){ int x, i, j, k, mask, best=1<<10, cnt; scanf("%d%d",&h,&w); REPONE(i,h)REPONE(j,w){ scanf("%d",&x); board[i][j] = x?true:false; } char ans[h][w+1]; char tmp[h][w+1]; REP(i,h)REP(j,w+1)ans[i][j]=(j==w)?'\0':'1'; REP(mask,1<<w){ cnt = 0; REPONE(i,h)REPONE(j,w)flipped[i][j] = board[i][j]; REP(j,w)if(mask & (1<<j)){ cnt++; tmp[0][j]='1'; REP(k,5) flipped[1+dy[k]][j+1+dx[k]] = !flipped[1+dy[k]][j+1+dx[k]]; }else tmp[0][j]='0'; REP(i,h)tmp[i][w]='\0'; for(i=2;i<=h;i++)REPONE(j,w){ if(flipped[i-1][j]){ cnt++; tmp[i-1][j-1]='1'; REP(k,5){ flipped[i+dy[k]][j+dx[k]] = !flipped[i+dy[k]][j+dx[k]]; } } else tmp[i-1][j-1]='0'; } REPONE(i,h)REPONE(j,w)if(flipped[i][j])break; if(i==h+1 && j==w+1 && cnt <= best){ if(cnt < best){ REP(k,h)strcpy(ans[k],tmp[k]); best = cnt; } else { bool f=false; REP(k,h){ if(f) strcpy(ans[k],tmp[k]); else if(strcmp(ans[k],tmp[k]) > 0){ f=true; strcpy(ans[k],tmp[k]); } else break; } } } } if(best<(1<<9)){ REP(i,h){ REP(j,w){ printf("%c",ans[i][j]); if(j<w-1)printf(" "); } printf("\n"); } } else{ printf("IMPOSSIBLE\n"); } return 0; }