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;
}