SRM 270 DIV1 Hard PackingShapes
問題
(問題の肝の部分のみ)
width*heightの長方形の中にx*yの長方形が回転してでも入るかどうかを判定せよ
- 全ての数値は整数, [1,1000]
解答
回転後の幅と高さは(x cosθ + y sinθ, x sinθ + y cosθ)。
それを適当にいろんな感じで二分探索しまくったら通った。
厳密な代数的解はEditorial参照
コメント
こういう適当に二分探索しまくるというのは結構使える。
しかしEditorialの解がわかってない。こういう式の解くのは苦手としてるな。普通に算数として練習するべきか
コード
#include <string> #include <vector> #include <sstream> #include <cmath> #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i)) #define pb(x) push_back(x) using namespace std; typedef vector<string> vs; typedef long double ld; struct PackingShapes { bool check(int w, int h, int x, int y, int t, bool b) { const ld pi = acos(-1.L); ld l = pi / 4. * t, u = pi / 4. * (t+1); rep(ii, 200) { ld m = (l+u) / 2; ((x*abs(cos(m))+y*abs(sin(m)) <= w) == b ? u : l) = m; } return x*abs(cos(u))+y*abs(sin(u)) <= w+1e-9L && x*abs(sin(u))+y*abs(cos(u)) <= h+1e-9L; } vector <string> tryToFit(int w, int h, vector <string> shapes) { vs r; rep(i, shapes.size()) { bool ok = false; stringstream ss(shapes[i]); string type; ss >> type; if(type == "CIRCLE") { int x; ss >> x; x *= 2; ok = x <= w && x <= h; }else { int x, y; ss >> x >> y; rep(wh, 2) { rep(xy, 2) { rep(j, 8) rep(b, 2) ok |= check(w, h, x, y, j, b); swap(x, y); } swap(w, h); } } r.pb(ok ? "YES" : "NO"); } return r; } };