TopCoder SRM 525 Div1 Easy DropCoins
問題
nxmの板がある。
それぞれのマスは空白'.'またはコインが1枚載っている'o'
板を1つ横または縦に動かす操作が出来る。
操作の結果板からはみでたコインは落ちてなくなる。
操作を繰り返して板に載っているコインの数をちょうどk枚にしたい。
そのような状態にいたるための操作の最低回数を求めよ。
不可能な場合は-1を返せ。
制約条件
n,m≦30
方針
残す長方形を一つ決める。
(x1,y1),(x2,y2)を残したとすると、その長方形だけを残すために必要な操作は、
min(x1,w-x2)*2+max(x1,w-x2)+min(y1,h-y2)*2+max(y2,h-y2)回
これを全通り試せばいい。
長方形内部のコインの個数は前処理をしておくことでO(1)で求められるが、
別に前処理をしなくても間に合う。
ソースコード
int sum[31][31]; int calc(int y1,int x1,int y2,int x2){ return sum[y2][x2]-sum[y2][x1]-sum[y1][x2]+sum[y1][x1]; } int calc2(int a,int b){ return min(a,b)*2+max(a,b); } class DropCoins { public: int getMinimum(vector <string> board, int K) { int h=board.size(), w=board[0].size(); memset(sum,0,sizeof(sum)); rep(i,h)rep(j,w)sum[i+1][j+1]=(board[i][j]=='o')+sum[i+1][j]+sum[i][j+1]-sum[i][j]; int ans=inf; rep(i,h)rep(j,w)for(int k=i;k<=h;k++)for(int l=j;l<=w;l++){ if(calc(i,j,k,l)==K)ans=min(ans,calc2(i,h-k)+calc2(j,w-l)); } return ans==inf?-1:ans; } };