惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
MyScale Blog
MyScale Blog
WordPress大学
WordPress大学
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
MongoDB | Blog
MongoDB | Blog
V
Vulnerabilities – Threatpost
月光博客
月光博客
罗磊的独立博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
F
Full Disclosure
Simon Willison's Weblog
Simon Willison's Weblog
D
DataBreaches.Net
T
Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
阮一峰的网络日志
阮一峰的网络日志
TaoSecurity Blog
TaoSecurity Blog
Microsoft Azure Blog
Microsoft Azure Blog
Scott Helme
Scott Helme
S
Securelist
W
WeLiveSecurity
K
Kaspersky official blog
The GitHub Blog
The GitHub Blog
Attack and Defense Labs
Attack and Defense Labs
博客园 - 三生石上(FineUI控件)
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
Stack Overflow Blog
Stack Overflow Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Security Latest
Security Latest
M
MIT News - Artificial intelligence
人人都是产品经理
人人都是产品经理
The Last Watchdog
The Last Watchdog
C
Check Point Blog
T
Troy Hunt's Blog
P
Proofpoint News Feed
J
Java Code Geeks
G
Google Developers Blog
Schneier on Security
Schneier on Security
Cyberwarzone
Cyberwarzone
S
Security @ Cisco Blogs
宝玉的分享
宝玉的分享
Recent Commits to openclaw:main
Recent Commits to openclaw:main
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
L
LINUX DO - 最新话题
Jina AI
Jina AI

博客园 - woodfish

偏序集的Dilworth定理 XJOJ历经2个月终于完成啦~~ fork()调用的一个趣题 实现google那种输入框提示的功能 POJ 3691 安徽第二题 有限状态自动机+DP 哈尔滨赛区网络预选赛总结 [计算几何]点集中的点能组成多少个正方形 [计算几何]POJ 1375 点对圆的切线+线段重叠 [计算几何]POJ 1556 判断线段相交+Dijkstra [计算几何]POJ 1266 三角形的外接圆 圆的参数方程 POJ 1026 置换群 [计算几何]POJ 1031 计算点对多边形的偏转角度 [计算几何]POJ2079 求点集中面积最大的三角形 [计算几何]POJ3608 求2个不相交凸包的最短距离 [计算几何]凸包的旋转卡壳算法 C++禁止一个类被继承的技术 C与汇编的接口技术 计算位数的3种方法 避免使用条件分支
[计算几何] POJ 1873 暴力+凸包
woodfish · 2008-09-08 · via 博客园 - woodfish

http://acm.pku.edu.cn/JudgeOnline/problem?id=1873

题目大意是从一个点集中选出一些点,是这些点的长度之和能够把剩下的点围起来,并且没个点有个权值,要求最后的选出的点的权值之和最小,如果有多个最小的,要求选出的点数最小。

由于点集数很小,n<=15,很容易想到枚举,每个点有选与不选2中状态,有2^n选点方式,没枚举一个选点方式,对剩下的点进行Graham扫描求凸包,看能不能满足要求。总的复杂度是O(2^n*n*logn)

一下有一些可以用到的优化手段:

1.枚举大可不必用dfs生成,可以直接用一个二进制数来表示选点集合。

2.在枚举出一个集合后,不要每次都求凸包,如果当前集合的权值之和>目前求出的最优权值之和,那就根本不用再往下面算了。

3.不要用vector来保存答案,这样肯定会超时。

#include <stdio.h>
#include 
<math.h>const int MAXN=15;struct point {
    
double x, y;
} pp[MAXN
+1],p[MAXN+1],h[MAXN+1];
int v[MAXN+1],l[MAXN+1];
int ans[MAXN+1],an;double mydistance(const point& p1,const point& p2) {
    
return sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double multiply(const point& sp,const point& ep,const point& op) {
    
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
int partition(point a[],int p,int r) {
    
int i=p,j=r+1,k;
    
double ang,dis;
    point R,S;
    k
=(p+r)/2;
    R
=a[p];
    a[p]
=a[k];
    a[k]
=R;
    R
=a[p];
    dis
=mydistance(R,a[0]);
    
while(1) {
        
while(1) {
            
++i;
            
if(i>r) {
                i
=r;
                
break;
            }
            ang
=multiply(R,a[i],a[0]);
            
if(ang>0)
                
break;
            
else if(ang==0) {
                
if(mydistance(a[i],a[0])>dis)
                
break;
            }
        }
        
while(1) {
             
--j;
            
if(j<p) {
                j
=p;
                
break;
            }
            ang
=multiply(R,a[j],a[0]);
            
if(ang<0)
                
break;
            
else if(ang==0) {
                
if(mydistance(a[j],a[0])<dis)
                    
break;
            }
        }
        
if(i>=j)break;
        S
=a[i];
        a[i]
=a[j];
        a[j]
=S;
    }
    a[p]
=a[j];
    a[j]
=R;
    
return j;
}
void anglesort(point a[],int p,int r) {
   
if(p<r) {
      
int q=partition(a,p,r);
      anglesort(a,p,q
-1);
      anglesort(a,q
+1,r);
   }
}
//对PointSet求凸包,点数为n,凸包上的点保存在ch中,点数位len
void Graham_scan(point PointSet[],point ch[],int n,int &len) {
    
int i,k=0,top=2;
    point tmp;
    
for(i=1;i<n;i++)
        
if ( PointSet[i].x<PointSet[k].x ||
            (PointSet[i].x
==PointSet[k].x) && (PointSet[i].y<PointSet[k].y) )
               k
=i;
    tmp
=PointSet[0];
    PointSet[
0]=PointSet[k];
    PointSet[k]
=tmp;
    anglesort(PointSet,
1,n-1);
    
if(n<3) {
        len
=n;
        
for(int i=0;i<n;i++) ch[i]=PointSet[i];
        
return ;
    }
    ch[
0]=PointSet[0];
    ch[
1]=PointSet[1];
    ch[
2]=PointSet[2];
    
for (i=3;i<n;i++) {
        
while (multiply(PointSet[i],ch[top],ch[top-1])>=0) top--;
            ch[
++top]=PointSet[i];
    }
    len
=top+1;
}
int main() {
    
int n;
    
int cases=0;
    
while(scanf("%d",&n)!=EOF&&n) {
        cases
++;
        
for(int i=0;i<n;i++)
            scanf(
"%lf %lf %d %d",&pp[i].x,&pp[i].y,&v[i],&l[i]);
        
int minv=1<<30;
        
double ex=0;for(int mask=0;mask<(1<<n);mask++) {
            
int tot=0;
            
int nowv=0;
            
int nowl=0;for(int i=0;i<n;i++) {
                
if(mask&(1<<i)) {
                    nowv
+=v[i];
                    nowl
+=l[i];
                }
else{
                    p[tot].x
=pp[i].x;
                    p[tot].y
=pp[i].y;
                    tot
++;
                }
            }
            
if(nowv>minv) continue;
            
if(tot==0 || tot==n) continue;
            
int len=0;
            
double nl=0;
            Graham_scan(p,h,tot,len);
            
for(int i=0;i<len;i++)
                nl
+=mydistance(h[i],h[(i+1)%len]);
            
if(nl<=nowl) {
                
if(nowv<minv || (nowv==minv&&n-tot<an)) {
                    minv
=nowv;
                    an
=0;
                    
for(int i=0;i<n;i++if(mask&(1<<i)) ans[an++]=i+1;
                    ex
=nowl-nl;
                }
            }
        }
        
if(cases>1) printf("\n");
        printf(
"Forest %d\n",cases);
        printf(
"Cut these trees:");
        
for(int i=0;i<an;i++) printf(" %d",ans[i]);
        printf(
"\n");
        printf(
"Extra wood: %.2f\n",ex);
    }
    
return 0;
}