kmjp's blog

競技プログラミング参加記です

KUPC2013 : D - カーペット

これ、途中でヒント情報を目にしてしまったんだよなぁ。
http://kupc2013.contest.atcoder.jp/tasks/kupc2013_d

問題

部屋の幅がNマス分あり、各マスにおける高さA[i]が与えられる。
この形状を長方形のカーペットを複数枚使って覆い尽くしたい。
カーペットのサイズは1枚1枚異なっていても良く、部分的に重ねても良い。

必要な最少のカーペット枚数を答えよ。

解法

問題の図を見ると思いつくのが、上から出っ張ってる部分を順に長方形を敷き詰めて消す、というもの。
消す、という処理があるのでデータ構造に迷うが、スタックを使って処理できる。

カーペットの高さを端から順に以下の様に処理していく。

  • スタック上に、処理するマスの高さより高い数値が入っていたら、それらをすべてpopする。そして取り除いた数をカーペット枚数として加算する。
  • スタックの最上位が、処理するマスの高さと同じなら何もせず、小さいなら処理するマスの高さをスタックにpushする。

最後に残ったスタック内の要素数だけ、カーペット枚数に加算して答えとなる。

なぜこれで行くか考えてみる。
Nマスの高さがすべて別々ならN枚のカーペットが無いと全面覆い尽くせない。
しかし、Nマスのうち同じ高さのマスがいくつかあり、かつそれらの間にそれより低いマスが無ければ、それらは1枚でまとめて処理できる。
この処理を「スタックの最上位と同じ高さならpushしない」という形で表現できている。

void solve() {
	int f,r,i,j,k,l,x,y,tx,ty;
	int N;
	stack<int> S;
	
	N=GETi();
	r=0;
	FOR(i,N) {
		j=GETi();
		while(!S.empty() && S.top()>j) {
			S.pop();
			r++;
		}
		if(S.empty() || S.top()<j) S.push(j);
	}
	r+=S.size();
	
	
	_P("%d\n",r);
}

まとめ

こういうマッチング系の問題はスタックを使えばいいんだな。
覚えておこう。