#include <iostream> #include <vector> #include <complex> #include <algorithm> #include <cmath> #include <cstdio> using namespace std; typedef complex<double> Point; double dot(Point a, Point b) { return a.real() * b.real() + a.imag() * b.imag(); } double cross(Point a, Point b) { return a.real() * b.imag() - a.imag() * b.real(); } namespace CCW{ enum{ RIGHT = 1, LEFT = -1, FRONT = 2, BACK = 2, OTHER = 0 }; }; int ccw(Point a, Point b, Point c) { b -= a; c -= a; if( cross(b, c) < 0 )return CCW::RIGHT; if( cross(b, c) > 0 )return CCW::LEFT; if( dot(b, c) < 0 )return CCW::BACK; if( norm(b) < norm(c) )return CCW::FRONT; return CCW::OTHER; } bool cmp_real(const Point &a, const Point &b) { if( a.imag() != b.imag() )return a.imag() < b.imag(); return a.real() < b.real(); } vector<Point> andrew(vector<Point> v) { if(v.size() < 3)return v; sort( v.begin(), v.end(), cmp_real ); vector<Point> r[2]; for(int i=0; i<2; ++i){ for(int j=0; j<v.size(); ++j){ r[i].push_back( v[j] ); while( 2 < r[i].size() ){ vector<Point> :: iterator itr = r[i].end(); if( ccw( *(itr-3), *(itr-2), *(itr-1) ) == CCW::RIGHT )break; else r[i].erase( itr - 2 ); } } if(i)break; for(int j=0; j<v.size(); ++j){ v[j].imag() *= -1; } } for(int i=r[1].size()-2; 0<i; --i){ r[1][i].imag() *= -1; r[0].push_back( r[1][i] ); } return r[0]; } double dist_pp(const Point &a, const Point &b) { double i = a.imag() - b.imag(); double r = a.real() - b.real(); return sqrt( i * i + r * r ); } int main(void) { int tree; while( cin >> tree && tree ){ vector<Point> v; double len[tree]; double val[tree]; for(int i=0; i<tree; ++i){ Point p; cin >> p.real() >> p.imag() >> val[i] >> len[i]; v.push_back( p ); } int bit = -1; double mx = 0; double l, f; for(int i=1; i<(1 << tree); ++i){ vector<Point> u; double sum_l = 0; double sum_v = 0; for(int j=0; j<tree; ++j){ if( i & (1 << j) ){ u.push_back( v[j] ); sum_v += val[j]; } else sum_l += len[j]; } u = andrew( u ); if(u.size() == 0)continue; double fance = dist_pp( u[0], u.back() ); for(int j=0; j+1<u.size(); ++j){ fance += dist_pp( u[j], u[j+1] ); } if(fance <= sum_l){ if(mx < sum_v){ mx = sum_v; bit = i; } } } double ex = 0; vector<Point> u; for(int i=0; i<v.size(); ++i){ if( bit & (1 << i) ){ u.push_back( v[i] ); } else ex += len[i]; } u = andrew( u ); ex -= dist_pp( u[0], u.back() ); for(int i=0; i+1<u.size(); ++i){ ex -= dist_pp( u[i], u[i+1] ); } static int cnt = 0; if(cnt) puts(""); printf("Forest %d\n", ++cnt); printf("Cut these trees:"); for(int i=0; i<tree; ++i){ if( bit & (1 << i) ); else printf(" %d", i+1); } puts(""); printf("Extra wood: %.2lf\n", ex); } return 0; }
6/20/2011
UVa811
全部試す。やるだけ。
登録:
コメントの投稿
(
Atom
)
0 件のコメント :
コメントを投稿