Uva5211/POJ1873 The Fortified Forest 凸包
题意:给出点集,每个点有个价值v和长度l,问把其中几个点取掉,用这几个点的长度能把剩下的点围住,要求剩下的点价值和最大,拿掉的点最少且剩余长度最长。
思路:1999WF中的水题。考虑到其点的数量最多只有15个,那么可以使用暴力枚举所有取点情况,二进制压缩状态,预处理出该状态下的价值,同时记录该状态拥有的点,并按价值排序。按价值枚举状态,并对拥有的这些点求凸包,check是否合法,找到一组跳出即可。然而POJ似乎没有SPJ,同样的代码POJ会超时,UVA60ms,可以在常数上优化,不预处理,实时判价值最大值,不使用结构体等
/** @Date : 2017-07-16 14:48:08
* @FileName: POJ 1873 凸包.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
#include <math.h>
//#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std; const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8; struct point
{
double x, y;
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.x + y * b.y;
}
double operator ^(const point &b) const
{
return x * b.y - y * b.x;
}
}; double xmult(point p1, point p2, point p0)
{
return (p1 - p0) ^ (p2 - p0);
} double distc(point a, point b)
{
return sqrt((double)((b - a) * (b - a)));
} int sign(double x)
{
if(fabs(x) < eps)
return 0;
if(x < 0)
return -1;
else
return 1;
}
//////////// point pt[50];
int v[50], l[50];
struct yuu
{
point p[50];
int val;
int cnt;
int len;
int sta;
double cst;
void init(){cnt = len = val = cst = 0;}
}tt[1 << 16]; point stk[50]; /*int cmpA(point a, point b)//以p[0]基准 极角序排序
{
int t = xmult(a, b, p[0]);
if(t > 0)
return 1;
if(t == 0)
return distc(a, p[0]) < distc(b, p[0]);
if(t < 0)
return 0;
}*/ int cmpB(yuu a, yuu b)//预处理用
{
if(a.val == b.val)
return a.cnt < b.cnt;
return a.val < b.val;
} int cmpC(point a, point b)//水平序排序
{
return sign(a.x - b.x) < 0 || (sign(a.x - b.x) == 0 && sign(a.y - b.y) < 0);
} /*void grahamS()
{
while(!s.empty())
s.pop();
for(int i = 0; i < min(n, 2); i++)
s.push(i);
int t = 1;
for(int i = 2; i < n; i++)
{
while(s.size() > 1)
{
int p2 = s.top();
s.pop();
int p1 = s.top();
if(xmult(p[p1], p[p2], p[i]) > 0)
{
s.push(p2);
break;
}
}
s.push(i);
}
}*/ int graham(int st)//水平序
{
sort(tt[st].p, tt[st].p + tt[st].cnt, cmpC);
int top = 0;
for(int i = 0; i < tt[st].cnt; i++)
{
while(top >= 2 && sign(xmult(stk[top - 2], stk[top - 1], tt[st].p[i])) <= 0)
top--;
stk[top++] = tt[st].p[i];
}
int tmp = top;
for(int i = tt[st].cnt - 2; i >= 0; i--)
{
while(top > tmp && sign(xmult(stk[top - 2],stk[top - 1] ,tt[st].p[i] )) <= 0)
top--;
stk[top++] = tt[st].p[i];
}
if(tt[st].cnt > 1)
top--;
return top;
} int check(int st)
{
int ma = graham(st);
double ans = 0;
stk[ma] = stk[0];
for(int i = 0; i < ma; i++)
ans += distc(stk[i + 1], stk[i]);
tt[st].cst = ans;
if(sign(tt[st].len - ans) < 0)
return 0;
return 1;
} int main()
{
int n;
int cc = 0;
while(~scanf("%d", &n) && n)
{
if(cc)
printf("\n");
cc++;
double x, y;
for(int i = 0; i < n; i++)
{
scanf("%lf%lf%d%d", &x, &y, v + i, l + i);
pt[i] = point(x, y);
}
int c = 0;
for(int st = 0; st < (1 << n); st++)//预处理
{
tt[st].sta = st;
tt[st].init();
c = 0;
for(int i = 0; i < n; i++)
{
if(st & (1 << i))
tt[st].len += l[i], tt[st].val += v[i];
else
tt[st].p[c++] = pt[i]; }
tt[st].cnt = c;
}
sort(tt, tt + (1 << n), cmpB); //////
for(int st = 0; st < (1 << n); st++)//遍历
{
if(check(st))
{
printf("Forest %d\n", cc);
printf("Cut these trees:");
for(int i = 0; i < n; i++)
{
if(tt[st].sta & (1 << i))
printf(" %d", i + 1);
}
printf("\nExtra wood: %.2lf\n", ((double)tt[st].len - tt[st].cst + eps));
break;
}
}
}
return 0;
}
Uva5211/POJ1873 The Fortified Forest 凸包的更多相关文章
- poj1873 The Fortified Forest 凸包+枚举 水题
/* poj1873 The Fortified Forest 凸包+枚举 水题 用小树林的木头给小树林围一个围墙 每棵树都有价值 求消耗价值最低的做法,输出被砍伐的树的编号和剩余的木料 若砍伐价值相 ...
- POJ 1873 The Fortified Forest [凸包 枚举]
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6400 Accepted: 1 ...
- POJ 1873 - The Fortified Forest 凸包 + 搜索 模板
通过这道题发现了原来写凸包的一些不注意之处和一些错误..有些错误很要命.. 这题 N = 15 1 << 15 = 32768 直接枚举完全可行 卡在异常情况判断上很久,只有 顶点数 &g ...
- POJ 1873 UVA 811 The Fortified Forest (凸包 + 状态压缩枚举)
题目链接:UVA 811 Description Once upon a time, in a faraway land, there lived a king. This king owned a ...
- POJ 1873 The Fortified Forest 凸包 二进制枚举
n最大15,二进制枚举不会超时.枚举不被砍掉的树,然后求凸包 #include<stdio.h> #include<math.h> #include<algorithm& ...
- 简单几何(凸包+枚举) POJ 1873 The Fortified Forest
题目传送门 题意:砍掉一些树,用它们做成篱笆把剩余的树围起来,问最小价值 分析:数据量不大,考虑状态压缩暴力枚举,求凸包以及计算凸包长度.虽说是水题,毕竟是final,自己状压的最大情况写错了,而且忘 ...
- POJ 1873 The Fortified Forest(枚举+凸包)
Description Once upon a time, in a faraway land, there lived a king. This king owned a small collect ...
- The Fortified Forest - POJ 1873(状态枚举+求凸包周长)
题目大意:有个国王他有一片森林,现在他想从这个森林里面砍伐一些树木做成篱笆把剩下的树木围起来,已知每个树都有不同的价值还有高度,求出来砍掉那些树可以做成篱笆把剩余的树都围起来,要使砍伐的树木的价值最小 ...
- POJ 1873 The Fortified Forest(凸包)题解
题意:二维平面有一堆点,每个点有价值v和删掉这个点能得到的长度l,问你删掉最少的价值能把剩余点围起来,价值一样求删掉的点最少 思路:n<=15,那么直接遍历2^15,判断每种情况.这里要优化一下 ...
随机推荐
- C++:构造函数1——普通构造函数
前言:构造函数是C+中很重要的一个概念,这里对其知识进行一个简单的总结 一.构造函数的定义 1.类中的构造函数名与类名必须相同 2.构造函数没有函数的返回类值型说明符 [特别注意]: a.构造函数的返 ...
- 在pycharm中使用scrapy爬虫
目标在Win7上建立一个Scrapy爬虫项目,以及对其进行基本操作.运行环境:电脑上已经安装了python(环境变量path已经设置好), 以及scrapy模块,IDE为Pycharm .操作如下: ...
- C#高级编程 (第六版) 学习 第四章:继承
第四章 继承 1,继承的类型 实现继承: 一个类派生于一个基类型,拥有该基类型所有成员字段和函数. 接口继承 一个类型只继承了函数的签名,没有继承任何实现代码. 2,实现继承 class MyDe ...
- Oracle win64_12g 安装
1.Oracle win64_12g 安装 1.下载安装包:这里需要自己注册一下,然后就可以登录下载软件了. 下载地址: http://www.oracle.com/technetwork/datab ...
- 1st 本周工作量及进度统计
1. 项目:英文文章词频统计 项目类型:个人项目 项目完成情况:已完成 项目日期:2016.9.6 C(类别) C(内容) S(开始时间) ST(结束时间) I(耽误时间) △(实际时间) 分析 需求 ...
- 操纵Excel文件的 ExcelUtil 类 !
package FileDemo1; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStr ...
- css3 flex属性flex-grow、flex-shrink、flex-basis学习笔记
最近在研究css3的flex.遇到的flex:1;这一块,很是很纠结,flex-grow.flex-shrink.flex-basis始终搞不清,最经搜集了大量的介绍,应该能算是明白了.网上大部分解释 ...
- javascript之彻底理解valueOf, toString
参与运算的都是简单类型(一般就字符串和数字), 复杂类型是不参与运算的. ***当对象(非简单类型)用作键时,会先调用toString()方法把对象转化成字符串 var a = {}, b = ...
- Java设计模式 - 单例模式 (懒汉方式和饿汉方式)
概念: Java中单例模式是一种常见的设计模式,单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的写法有好几种,这 ...
- SQL入门之集合操作
尽管可以在与数据库交互时一次只处理一行数据,但实际上关系数据库通常处理的都是数据的集合.在数学上常用的集合操作为:并(union),交(intersect),差(except).对于集合运算必须满足下 ...