kmjp's blog

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

Codeforces #322 Div2 D. Three Logos

サンプルがだいぶヒント。
http://codeforces.com/contest/581/problem/D

問題

3つの長方形の辺の長さが与えられる。
3つを連結して正方形を作れるか、作れるならその形状を答えよ。
なお各長方形は90度回転させても良い。

解法

3つの長方形を連結して正方形を作る場合、全体を回転または反転させると以下のいずれかに帰着する。

  • 同じ幅の長方形が3つが縦に連結する
  • 高さの同じ2つの長方形横に連結し、その上に同じ幅の長方形が乗る。

具体例は下記の通り。

111111  111111
222222  111111
222222  223333
333333  223333
333333  223333
333333  223333

あとは3つの長方形が上記1,2,3のどれに相当するか、また90度回転の有無を総当たりして、上記2形状のどちらかにマッチするか判定すればよい。

int X[3],Y[3];
int X2[3],Y2[3];
pair<int,char> P[3];
void solve() {
	int i,j,k,l,r,x,y; string s;
	
	FOR(i,3) cin>>X2[i]>>Y2[i], P[i]={i,'A'+i};
	
	do {
		for(int mask=0;mask<8;mask++) {
			FOR(i,3) {
				if(mask&(1<<i)) X[i]=X2[P[i].first],Y[i]=Y2[P[i].first];
				else X[i]=Y2[P[i].first],Y[i]=X2[P[i].first];
			}
			
			// straight
			if(X[0]==X[1] && X[1]==X[2] && X[0]==Y[0]+Y[1]+Y[2]) {
				_P("%d\n",Y[0]+Y[1]+Y[2]);
				FOR(i,3) {
					FOR(y,Y[i]) {
						FOR(x,X[i]) _P("%c",P[i].second);
						_P("\n");
					}
				}
				return;
			}
			
			if(X[0]+X[1]==X[2] && Y[0]==Y[1] && X[2]==Y[0]+Y[2]) {
				_P("%d\n",Y[0]+Y[2]);
				FOR(y,Y[2]) {
					FOR(x,X[2]) _P("%c",P[2].second);
					_P("\n");
				}
				FOR(y,Y[0]) {
					FOR(x,X[0]) _P("%c",P[0].second);
					FOR(x,X[1]) _P("%c",P[1].second);
					_P("\n");
				}
				return;
			}
		}
	} while(next_permutation(P,P+3));
	_P("-1\n");
	
}

まとめ

サンプルで上記基本的な2形状が出てきてるのが親切だよね。