POJ 1873 /// 状压+凸包
题目大意:
国王有一片森林,巫师需要从所有树中选出一些做成围栏把其他树围起来,
每棵树都有其对应的价值 v 和能作为围栏的长度 l
要求最小价值,若存在多种最小价值的方案则选择余下长度更少的
树木较少 状态压缩 枚举所有状态
计算当前的状态 被选中的 树的价值和长度
其他 被围起来(未被选中)的树去求凸包
计算凸包的边长(即围栏的最小长度)
判断选中的树是否能围住凸包 再更新答案
#include <cstdio>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std; const double eps=1e-;
double add(double a,double b) {
if(abs(a+b)<eps*(abs(a)+abs(b))) return ;
return a+b;
}
struct P {
double x,y;
P(){};
P(double _x,double _y):x(_x),y(_y){};
P operator - (P p) {
return P(add(x,-p.x),add(y,-p.y)); }
P operator + (P p) {
return P(add(x,p.x),add(y,p.y)); }
P operator * (double d) {
return P(x*d,y*d); }
double dot(P p) {
return add(x*p.x,y*p.y); }
double det(P p) {
return add(x*p.y,-y*p.x); }
}p1[], p2[], p3[];
int n;
double v[], l[], ansv, ansl;
bool cmp(P a,P b) {
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
double length(P a,P b) {
return sqrt((a-b).dot(a-b));
}
double andrew(int n)
{
sort(p2,p2+n,cmp);
int k=;
for(int i=;i<n;i++) {
while(k> && (p3[k-]-p3[k-]).det(p2[i]-p3[k-])<=)
k--;
p3[k++]=p2[i];
}
for(int i=n-,t=k;i>=;i--) {
while(k>t && (p3[k-]-p3[k-]).det(p2[i]-p3[k-])<=)
k--;
p3[k++]=p2[i];
} // 凸包上的点存入p3 double res=;
for(int i=;i<k;i++) // 计算凸包边长 即围栏长度
res+=length(p3[i],p3[i-]);
return res;
}
bool solve(int task)
{
int cnt=, t=task;
double cntv=, cntl=;
for(int i=;i<n;i++) {
if(task&) cntv+=v[i], cntl+=l[i]; // 被选中的 计算价值及长度
else p2[cnt++]=p1[i]; // 为被选中的存入p2 待求凸包
task >>= ;
}
if(cntv>ansv) return ; // 价值大于已有答案价值 返回0
double tblen=andrew(cnt); // 求凸包边长 即围栏所需长度
if(tblen>cntl) return ; // 若长度不足于围成围栏 返回0 if(cntv==ansv) ansl=min(ansl,cntl-tblen); // 更新余下长度的答案
else ansv=cntv, ansl=cntl-tblen; // 存在更小的价值 更新价值和长度
return ; // 更新了答案 返回1 记录新的状态
} int main()
{
int c=;
while(~scanf("%d",&n)) {
if(n==) break; c++;
for(int i=;i<n;i++) {
scanf("%lf%lf",&p1[i].x,&p1[i].y);
scanf("%lf%lf",&v[i],&l[i]);
} int ans;
ansv=ansl=INF;
int N=(<<n)-;
for(int i=;i<N;i++) // 枚举所有状态
if(solve(i)) ans=i; printf("Forest %d\n",c);
printf("Cut these trees:");
for(int i=;i<n;i++) {
if(ans & ) printf(" %d",i+);
ans >>= ;
}
printf("\nExtra wood: %.2f\n\n",ansl);
} return ;
}
POJ 1873 /// 状压+凸包的更多相关文章
- POJ 2923 状压好题
Relocation Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2631 Accepted: 1075 Descri ...
- POJ 3254 (状压DP) Corn Fields
基础的状压DP,因为是将状态压缩到一个整数中,所以会涉及到很多比较巧妙的位运算. 我们可以先把输入中每行的01压缩成一个整数. 判断一个状态是否有相邻1: 如果 x & (x << ...
- POJ 3254 状压DP
题目大意: 一个农民有一片n行m列 的农场 n和m 范围[1,12] 对于每一块土地 ,1代表可以种地,0代表不能种. 因为农夫要种草喂牛,牛吃草不能挨着,所以农夫种菜的每一块都不能有公共边. ...
- poj 1170状压dp
题目链接:https://vjudge.net/problem/POJ-1170 题意:输入n,表示有那种物品,接下来n行,每行a,b,c三个变量,a表示物品种类,b是物品数量,c代表物品的单价.接下 ...
- POJ 2411 状压DP经典
Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 16771 Accepted: 968 ...
- poj 3254 状压dp入门题
1.poj 3254 Corn Fields 状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...
- poj 1185(状压dp)
题目链接:http://poj.org/problem?id=1185 思路:状态压缩经典题目,dp[i][j][k]表示第i行状态为j,(i-1)行状态为k时最多可以放置的士兵个数,于是我们可以得到 ...
- poj 1185 状压dp+优化
http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 291 ...
- POJ 2441 状压DP
Arrange the Bulls Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 5289 Accepted: 2033 ...
随机推荐
- Zookeeper_ZAB协议
ZAB协议 ZAB协议简介 ZAB:(Zookeeper Atomic Broadcast),zk原子消息广播协议,是专为ZK设计的一中支持崩溃恢复的原子广播协议,是一种Paxos协议的优化算法,在Z ...
- 云栖干货回顾 | 云原生数据库POLARDB专场“硬核”解析
POLARDB是阿里巴巴自主研发的云原生关系型数据库,目前兼容三种数据库引擎:MySQL.PostgreSQL.Oracle.POLARDB的计算能力最高可扩展至1000核以上,存储容量可达100TB ...
- TopCoder[TCO2016 Round 1A]:EllysTree(1000)
Problem Statement Elly has a graph with N+1 vertices, conveniently numbered from 0 to N. The gr ...
- 51 eigen、boost等基础库学习
0 引言 eigen库是一个高层次的C++库,有效支持线性代数,矩阵和矢量运算,数值分析及其相关的算法.eigen除了C++标准库之外,不需要任何其他的依赖包.Eigen使用的CMake建立配置文件和 ...
- BZOJ 1415: [Noi2005]聪聪和可可(记忆化搜索+期望)
传送门 解题思路 还是比较简答的一道题.首先\(bfs\)把每个点到其他点的最短路求出来,然后再记忆化搜索.记搜的时候猫的走法是确定的,搜一下老鼠走法就行了. 代码 #include<iostr ...
- NX二次开发-UFUN获取直线的两个端点UF_CURVE_ask_line_data
NX9+VS2012 #include <uf.h> #include <uf_obj.h> #include <uf_ui.h> UF_initialize(); ...
- POJ2186-Tarjan-kosaraju-缩点
目录 目录 思路: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 目录 题意:传送门 原题目描述在最下面. A认为B优秀,B认为C优秀,则A认为C优秀.问有多少个人被其他所有人 ...
- PAT_A1086#Tree Traversals Again
Source: PAT A1086 Tree Traversals Again (25 分) Description: An inorder binary tree traversal can be ...
- csv转字典
with open('filename','r') as csv_f: reader = csv.reader(csv_f) fieldnames = next(reader) csv_reader ...
- codeforces round#524 C. Masha and two friends /// 矩形切割
题目大意: 给定n行m列的黑白棋盘如下 给定矩形的左下点x1 y1和右上点x2 y2将这个区域都涂成白色 再给定矩形的左下点x3 y3和右上点x4 y4将这个区域都涂成黑色 求最后棋盘内有分别多少个白 ...