POJ 1873 The Fortified Forest (凸包,狀態壓縮枚舉)__計算幾何

來源:互聯網
上載者:User

題目連結:http://poj.org/problem?id=1873


題意:給出一些樹,每棵樹有座標,高度,以及價值,要求砍掉一些樹,用那些木材,將其它樹圍起來,要求花最小的代價,代價相同,要求砍掉最少的樹。

最後輸出要砍掉哪幾棵樹和最後剩下多少長度的木材。


輸入:

6
 0  0  8  3
 1  4  3  2
 2  1  7  1
 4  1  2  3
 3  5  4  6
 2  3  9  8
3
 3  0 10  2
 5  5 20 25
 7 -3 30 32
0


n棵樹,每行一棵,座標,價值,高度。


因為樹的棵數不多,所以可以直接狀態壓縮枚舉來做,枚舉時要注意判斷砍0棵樹的情況。

2^15次方,然後對剩下的樹求一次凸包,求出凸包周長,判斷木材是否夠用,記錄最優解。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>using namespace std;const double eps = 1e-8;const double PI = acos(-1.0);int sgn(double x) {if(fabs(x) < eps)return 0;if(x < 0)return -1;  else return 1; }struct Point {  double x,y, v, l;Point(){}  Point(double _x,double _y) {   x = _x;y = _y;  }  Point operator -(const Point &b)const {   return Point(x - b.x,y - b.y);  }  double operator ^(const Point &b)const {   return x*b.y - y*b.x;  }    double operator *(const Point &b)const {   return x*b.x + y*b.y;  }  void transXY(double B) {   double tx = x,ty = y;   x = tx*cos(B) - ty*sin(B);   y = tx*sin(B) + ty*cos(B);  } };struct Line {  Point s,e; Line(){}  Line(Point _s,Point _e)  {   s = _s;e = _e;  } pair<int,Point> operator &(const Line &b)const {Point res = s;if(sgn((s-e)^(b.s-b.e)) == 0) {if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);             else return make_pair(1,res);         }         double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));res.x += (e.x-s.x)*t;         res.y += (e.y-s.y)*t;         return make_pair(2,res);     } };double dist(Point a,Point b) {     return sqrt((a-b)*(a-b)); }const int MAXN = 1010; Point list[MAXN]; int Stack[MAXN], top;bool _cmp(Point p1,Point p2) {  double tmp = (p1-list[0])^(p2-list[0]);  if(sgn(tmp) > 0)return true;  else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0)   return true;  else return false; }void Graham(int n) {Point p0;int k = 0;p0 = list[0];  for(int i = 1;i < n;i++)  {   if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )   {    p0 = list[i];    k = i;   }  }  swap(list[k],list[0]);  sort(list+1,list+n,_cmp); if(n == 1)  {top = 1;Stack[0] = 0;return;}if(n == 2)  {   top = 2;   Stack[0] = 0;   Stack[1] = 1;   return ;  }  Stack[0] = 0;  Stack[1] = 1;  top = 2;  for(int i = 2;i < n;i++)  {   while(top > 1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0)top--;   Stack[top++] = i;  } } Point tree[20];int main() {int n;int kase = 1; while(~scanf("%d", &n), n) { printf("Forest %d\n", kase++); int i, j; for(i = 0; i < n; i++) { scanf("%lf %lf %lf %lf", &tree[i].x, &tree[i].y, &tree[i].v, &tree[i].l); } double ansc = 10000000, ansl;int anst[20];int num = 0; for(i = 0; i < 1 << n; i++) { int cnt = 0; double len1 = 0, len2 = 0, cost = 0; for(j = 0; j < n; j++) { if(i >> j & 1) { list[cnt++] = tree[j]; } else { len2 += tree[j].l; cost += tree[j].v; } } if(cnt == 0) continue;  //砍0棵樹  Graham(cnt); for(j = 0; j < top; j++) { len1 += dist(list[Stack[j]], list[Stack[(j + 1) % top]]); } if(len1 <= len2) { if(ansc > cost) { ansc = cost; ansl = len2 - len1; num = 0; for(j = 0; j < n; j++) { if(!(i >> j & 1)) { anst[num++] = j; } } } else if(ansc == cost){ if(n - cnt < num) { ansc = cost; ansl = len2 - len1; num = 0; for(j = 0; j < n; j++) { if(i >> j & 1) { anst[num++] = j; } } } } } } printf("Cut these trees:"); for(i = 0; i < num; i++) { printf(" %d", anst[i] + 1); } printf("\n"); printf("Extra wood: "); printf("%.2lf\n\n", ansl); }return 0;}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.