The Fortified Forest POJ - 1873 (二进制枚举+凸包)

题目地址:http://poj.org/problem?id=1873
二进制枚举所有被删的点,求出能构成围墙的树木的最大价值组合。
另外,G++不要用 %.2lf 今天又在这W了 换成C++ A了

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<string.h>
using namespace std;
const int MAXN=1005;
const double PI=acos(-1.0);

struct point
{
    int x,y,l,v;
};
point list[MAXN];
point list1[MAXN];
int stack[MAXN],top;

int cross(point p0,point p1,point p2) //计算叉积  p0p1 X p0p2
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}
double dis(point p1,point p2)  //计算 p1p2的 距离
{
    return sqrt((double)((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y)));
}
bool cmp(point p1,point p2) //极角排序函数 , 角度相同则距离小的在前面
{
    int tmp=cross(list[0],p1,p2);
    if(tmp>0) return true;
    else if(tmp==0&&dis(list[0],p1)<dis(list[0],p2)) return true;
    else return false;
}
void init(int n) //输入,并把  最左下方的点放在 list[0]  。并且进行极角排序
{
    int i,k;
    point p0;
   // scanf("%d%d",&list[0].x,&list[0].y);
    p0.x=list[0].x;
    p0.y=list[0].y;
    k=0;
    for(i=1;i<n;i++)
    {
       // scanf("%d%d",&list[i].x,&list[i].y);
        if( (p0.y>list[i].y) || ((p0.y==list[i].y)&&(p0.x>list[i].x)) )
        {
            p0.x=list[i].x;
            p0.y=list[i].y;
            k=i;
        }
    }
    list[k]=list[0];
    list[0]=p0;
    sort(list+1,list+n,cmp);
}
void graham(int n)
{
    int i;
    if(n==1) {top=0;stack[0]=0;}
    if(n==2)
    {
        top=1;
        stack[0]=0;
        stack[1]=1;
    }
    if(n>2)
    {
        for(i=0;i<=1;i++) stack[i]=i;
        top=1;

        for(i=2;i<n;i++)
        {
            while(top>0&&cross(list[stack[top-1]],list[stack[top]],list[i])<0) top--;
            top++;
            stack[top]=i;
        }
    }
}
int main()
{

  int n,ans,sum,sumv,xx,t;
  double suml,ans1,res;
  t=1;
  while(scanf("%d",&n)!=EOF)
  {
      if(n==0) break;
      for(int i=0;i<n;i++)
        scanf("%d%d%d%d",&list1[i].x,&list1[i].y,&list1[i].v,&list1[i].l);
    sum=990000;
      for(int i=1;i<(1<<n)-1;i++)
      {
          ans=0;
          suml=0;sumv=0;
          for(int j=0;j<n;j++)
          {
              if(i&(1<<j))
              {
                  sumv+=list1[j].v;
                  suml+=(double)list1[j].l;
              }
              else
              {
                  list[ans].x=list1[j].x;
                  list[ans++].y=list1[j].y;
              }
          }
          init(ans);
          graham(ans);
          top++;
          res=0;
            for(int k=0;k<top;k++)
            {
                 int j=(k+1)%top;
                  res+=dis(list[stack[k]],list[stack[j]]);
            }

            if(suml>res)
            {
                if(sum>sumv)
                {
                    ans1=suml-res;
                    sum=sumv;
                    xx=i;
                }
            }
      }
      printf("Forest %d\n",t);
      printf("Cut these trees: ");
      for(int j=0;j<n;j++)
      {
          if(xx&(1<<j))
            printf("%d ",j+1);
      }
      printf("\n");
      printf("Extra wood: %.2lf\n",ans1);
      printf("\n");
      t++;
  }
    return 0;
}
/*
Forest 1
Cut these trees: 2 4 5
Extra wood: 3.16
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值