TopCoder SRM 383 Div1 Medium FloorBoards
問題
room[i][j]のグリッドで表されるような長方形の部屋がある。
room[i][j]が'#'であるとき、(i,j)は柱があり、'.'であるとき(i,j)には何もない。
何もないマス全てに板を敷きたい。
板は、幅が1で、長さは自由である。
板は最低で何枚必要か求めよ。
板同士が重なったり、板がグリッドの外にはみでたりしてはならない。
制約条件
roomの行≦10
roomの列≦10
方針
動的計画法による。
dp[i][j][mask]を、i行目まで全て敷いて、i行目はj列まで板を敷いていて、
上一列分の板の向きをビットで表した整数がmaskであるような状態にするために必要な板の最小枚数とする。
(i,j)のマスには板を縦または横にするという2通りの敷き方がある。
板を縦に敷いたとき、一つ上のマスが縦向きならつなげられるので、新たなコストはかからない。
同様に横に敷いたとき、一つ左のマスが横向きならば新たなコストがかからない。
このようにテーブルを更新していくDPにより最適解が求まる。
ソースコード
int h,w; int dp[11][11][1<<10]; class FloorBoards { public: int layout(vector <string> room) { h=room.size(); w=room[0].size(); rep(i,h+1)rep(j,w+1)rep(k,1<<w)dp[i][j][k]=inf; dp[0][0][0]=0; rep(i,h){ rep(j,w)rep(k,1<<w)rep(l,2){ int mask=k&~(1<<j)|l<<j, cost=dp[i][j][k]+1; if(l==0&&i&&!(k&1<<j)&&room[i-1][j]=='.'|| l==1&&j&&(k&1<<j-1)&&room[i][j-1]=='.'|| room[i][j]=='#')cost--; dp[i][j+1][mask]=min(dp[i][j+1][mask],cost); } rep(k,1<<w)dp[i+1][0][k]=dp[i][w][k]; } int ans=inf; rep(i,1<<w)ans=min(ans,dp[h][0][i]); return ans; } };