kengo92iの日記

プログラミングとかやったことの記録を書いていきます。

AOJ-1149 : ケーキカット

Cut the Cakes | Aizu Online Judge

概要

長方形のケーキを,縦横にカットして切り分けていきます.切り分けたケーキには識別番号が付けられ,識別番号は,1回カットが行われるたびに付け替えられます.最終的に切り分けたそれぞれのケーキの面積を昇順に出力します.

解法

ケーキのカットする位置は左上から,縦横の長さがマイナスになるまで交互に引き続けます.値を引いた回数が偶数か奇数で,縦横のカットを判断する.(mod使った方が良かったみたいです)

識別番号の付け方は,構造体ソートで解決できます.識別番号の付ける条件が以下のように説明されています.

  1. 先に生まれたピースほど識別番号が小さい.
  2. 1回のカットで生まれる二つのピースについては,(上から見た)面積の小さい方が識別番号も小さい. 二つのピースの面積が同じになる場合には,どちらの識別番号が小さいと考えても構わない(どちらにしても最終的な答えには影響しない).

なので,構造体で以下のように定義しています.

bool operator<(const cake &c) const {
	if(turn != c.turn) { return turn < c.turn; }
	return area < c.area;
}

最後に,それぞれのピースの面積を取り出して,昇順ソートすれば終わりです.

ソースコード

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1149

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<cmath>
#include<climits>
#include<ctime>
#include<cstring>
#include<numeric>

#define ALL(v) (v).begin(),(v).end()
#define REP(i,p,n) for(int i=p;i<(int)(n);++i)
#define rep(i,n) REP(i,0,n)
#define dump(a) (cerr << #a << "=" << (a) << endl)
#define DUMP(list) cout << "{ "; for(auto nth : list){ cout << nth << " "; } cout << "}" << endl;

using namespace std;

struct cake {
	int w, d, area, turn;
	cake(int w_, int d_, int turn_)
		: w(w_), d(d_), area(w_*d_), turn(turn_) {}
	bool operator<(const cake &c) const {
		if(turn != c.turn) { return turn < c.turn; }
		return area < c.area;
	}
};

vector<cake> cakes;

int main() {
	int n, w, d;
	while(cin >> n >> w >> d, w) {
		int turn=0;
		cakes.clear();
		cakes.push_back(cake(w, d, turn));
		int p, s;
		rep(i, n) {
			++turn;
			cin >> p >> s; p--;
			cake piece = cakes[p];
			cakes.erase(cakes.begin() + p);
			
			int k=1, diff=s;
			for(; diff > 0; ++k) {
				diff -= (k % 2) ? piece.w : piece.d;
			}
			
			diff *= -1;
			if(k % 2) { //縦分割
				int d1 = piece.d - diff;
				int d2 = diff;
				cakes.push_back(cake(piece.w, d1, turn));	
				cakes.push_back(cake(piece.w, d2, turn));	
			} 
			else { //横分割
				int w1 = piece.w - diff;
				int w2 = diff;
				cakes.push_back(cake(w1, piece.d, turn));	
				cakes.push_back(cake(w2, piece.d, turn));	
			}

			sort(ALL(cakes));
		}

		vector<int> result;
		rep(i, cakes.size()) result.push_back(cakes[i].area);

		sort(ALL(result));
		rep(i, result.size()) {
			if(i != 0) cout << " ";
			cout << result[i];
		}
		cout << endl;
	}
	return 0;
}