好题-HDU5135-壮压|贪心-Little Zu Chongzhi's Triangles

本文探讨了如何通过编程解决给定多个木棍时,如何选取木棍组合以构成尽可能多且面积最大的三角形的问题。提供了两种解决方案:一种使用动态规划结合状态压缩,另一种采用贪心算法。

http://acm.hdu.edu.cn/showproblem.php?pid=5135
给定m个木棍,把这些木棍组成三角形。可以不用完,问你最多摆成的三角形面积和最大。
我开始的思路是 暴力枚举所有状态,然后在判断是否有交集。。
因为要考虑要组成多少个,所以还要三个if。。
全部搞定之后,在用压位的思想来判断,但是后来觉得压位判断有点麻烦,如果一个三角形占了1 3 5,还要考虑他和一个,两个,三个三角形重复的情况。。。
后来队友发现直接排序升序后,从大到小贪心取就行。因为海伦公式。P=(a+b+c)/2;
后来又看了壮压。。mmp这不是我的想法么qwq

#include <bits/stdc++.h>
using namespace std;
/*由海伦公式可知,边长越大,面积越大。
 或者用壮压的思想做一下。
1 海伦 公式。
或者用壮压的思想来一下。。
*/
vector<pair<double,int> >v;
double dp[1<<15];
double a[50];
int main(){
    int m;
    while(~scanf("%d",&m)){
          if(!m) break;
          v.clear();
          for(int i=0;i<1<<m;i++)
            dp[i]=0.0;
          for(int i=0;i<m;i++)
              scanf("%lf",&a[i]);
              sort(a,a+m);
          for(int i=0;i<m;i++){
              for(int j=i+1;j<m;j++)
              for(int k=j+1;k<m;k++){
                 if(a[i]+a[j]>a[k]&&a[j]-a[i]<a[k]){
                 int tmp=(1<<i)|(1<<j)|(1<<k);
                 double  p=(a[i]+a[j]+a[k])/2;
                 double x=sqrt(p*(p-a[i])*(p-a[j])*(p-a[k]));
                 //cout<<x<<" "<<p<<endl;
                 v.push_back(make_pair(x,tmp));
                 }
              }
          }
          int s=(1<<m)-1;
          dp[0]=0.0;
          for(int i=0;i<=s;i++){
              for(int j=0;j<v.size();j++){
                 if((i&v[j].second)==0){
                  dp[i|v[j].second]=max(dp[i|v[j].second],dp[i]+v[j].first);//转移一个状态、
                 }
              }
          }
          //for(int i=0;i<=s;i++)
            //cout<<i<<" "<<dp[i]<<endl;
          double ans=0;
          for(int i=0;i<=s;i++)
                ans=max(dp[i],ans);
          printf("%.2f\n",ans);
    }
    return 0;
}

贪心。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <iostream>
#include <cstdio>
double getS(int a,int b,int c)
{
    double d=(double)(a*a+b*b-c*c)/(2.0*a*b);
    double e=sqrt(1-d*d);
    double ans=0.5*a*b*e;
    return ans;
}
using namespace std;
int a[15];
int main()
{
    int n;
    //cout<<getS(5,5,4)+getS(4,3,3);
    while(scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
            sort(a,a+n,greater<int>());
        double sum=0;

       for(int i=0;i<n-2;i++)
            {
                if((a[i+2]+a[i+1])>a[i]&&(a[i+1]-a[i+2])<a[i])
                {
                    sum+=getS(a[i],a[i+1],a[i+2]);
                    //cout<<"sum=  "<<getS(a[i],a[i+1],a[i+2])<<endl;
                    i+=2;
                }

            }
            //cout<<sum<<endl;
        printf("%.2f\n",sum);
    }
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值