ICPC2017 国内予選 H 等積変形
問題
面積の等しい三角形A, Bが与えられる。
三角形Aに対し等積変形(二頂点を固定し、残り一頂点を三角形の面積が変わらないように動かす操作)を繰り返し三角形Aを三角形Bに重ねたい。
必要な操作の最低回数(あるいは4回以内にはできない)を求めよ。
解法
通ったけど正当性が怪しい。
全ての操作は可逆なので三角形Aだけでなく三角形Bも自由に等積変形してよいと考えていい。
三角形に対する操作で意味があるのは
- Aの頂点をBの頂点まで動かして重ねる
- Bの頂点をAの頂点まで動かして重ねる
- Aの頂点とBの頂点を両方動かしてどこかの場所で一致させる
の二通り。これを全部試す。
ソースコード
//幾何のライブラリ部分は略 bool onL(const L &l, const P &p){ return abs(ccw(l[0], l[1], p)) != 1; } int one(G a, G b){ int ans = inf; //a[s]がb[t]に直接重なる if(onL(L(a[2], a[2] + a[0] - a[1]), b[2])) return 1; //a[s]とb[t]をどっかで重ねる double c = cross(a[1] - a[0], b[1] - b[0]); if(abs(c) > EPS) ans = min(ans, 2); return ans; } int two(G a, G b){ int ans = inf; for(int s = 1; s < 3; s++) for(int t = 1; t < 3; t++){ swap(a[s], a[1]); swap(b[t], b[1]); //a[s]がb[t]に直接重なる if(onL(L(a[1], a[1] + a[0] - a[2]), b[1])){ P p = a[1]; a[1] = b[1]; ans = min(ans, one(a, b) + 1); ans = min(ans, one(b, a) + 1); //dbg(s, t, ans); a[1] = p; } //a[s]とb[t]をどっかで重ねる double c = cross(a[2] - a[0], b[2] - b[0]); if(abs(c) > EPS){ P p = crosspoint(L(a[1], a[1] + a[2] - a[0]), L(b[1], b[1] + b[2] - b[0])); P a0 = a[1]; a[1] = p; P b0 = b[1]; b[1] = p; ans = min(ans, one(a, b) + 2); ans = min(ans, one(b, a) + 2); //dbg(s, t, ans); a[1] = a0; b[1] = b0; } swap(a[s], a[1]); swap(b[t], b[1]); } return ans; } int three(G a, G b){ int ans = inf; rep(s, 3) rep(t, 3){ swap(a[s], a[0]); swap(b[t], b[0]); //a[s]がb[t]に直接重なる if(onL(L(a[0], a[0] + a[1] - a[2]), b[0])){ P p = a[0]; a[0] = b[0]; ans = min(ans, two(a, b) + 1); ans = min(ans, two(b, a) + 1); //dbg(s, t, ans); a[0] = p; } //a[s]とb[t]をどっかで重ねる double c = cross(a[2] - a[1], b[2] - b[1]); if(abs(c) > EPS){ P p = crosspoint(L(a[0], a[0] + a[2] - a[1]), L(b[0], b[0] + b[2] - b[1])); P a0 = a[0]; a[0] = p; P b0 = b[0]; b[0] = p; ans = min(ans, two(a, b) + 2); ans = min(ans, two(b, a) + 2); //dbg(s, t, ans); a[0] = a0; b[0] = b0; } swap(a[s], a[0]); swap(b[t], b[0]); } return ans; } int main(){ while(1){ G a, b; rep(i, 3){ int x, y; if(!(cin >> x >> y)) exit(0); a.emplace_back(x, y); } rep(i, 3){ int x, y; cin >> x >> y; b.emplace_back(x, y); } int ans = inf; ans = min(ans, three(a, b)); ans = min(ans, three(b, a)); if(ans >= 5) cout << "Many" << endl; else cout << ans << endl; } return 0; }