HDU 5135

题意略。

思路:

本题开始我先写了一发dfs暴力,然而递归程度太深,导致爆栈。仔细回想一下dfs的过程,发现最不好处理的就是每收集到3个木棍,才能构成一个三角形。

并且,还有一个隐患就是不能完全枚举出来木棍的组合情况。那么我们可以预先把木棍的组合情况枚举出来,按照题意,不会超过220种现在我们就是

想在这些组合情况中谋求最大面积。这样,我们可以把这个题看成为一个特殊的背包问题。

令dp[i][state]为在0~i中,当前恰好持有的木棍情况为state,且这些木棍要全部用完,我可以谋取的最大利益。那么状态转移方程为:

dp[i][state] = max(dp[i - 1][state],dp[i - 1][state - 当前方案所需木棍情况] + area);

详见代码:

#include<bits/stdc++.h>
#define maxn 251
#define maxn1 5000
using namespace std;

struct node{
    double val;
    int state;
    node(double a = 0,int b = 0){
        val = a,state = b;
    }
};

double store[15];
node depot[maxn];
double dp[2][maxn1];
int n;

double cal(double a,double b,double c){
    double p = (a + b + c) / 2;
    return sqrt(p * (p - a) * (p - b) * (p - c));
}
bool judge(double a,double b,double c){
    return (fabs(a - b) < c && c < a + b);
}
void depart(int s){
    for(int i = 0;i < n;++i){
        if(s & (1<<i)) printf("1");
        else printf("0");
    }
}

int main(){
    while(scanf("%d",&n) == 1 && n){
        for(int i = 0;i < n;++i) scanf("%lf",&store[i]);
        int tail = 0;
        for(int i = 0;i < n;++i){
            for(int j = i + 1;j < n;++j){
                for(int k = j + 1;k < n;++k){
                    double a = store[i],b = store[j],c = store[k];
                    if(!judge(a,b,c)) continue;
                    depot[tail++] = node(cal(a,b,c),(1<<i) | (1<<j) | (1<<k));
                }
            }
        }
        for(int i = 0;i < 2;++i){
            for(int j = 0;j < maxn1;++j) dp[i][j] = -1;
        }
        dp[0][depot[0].state] = depot[0].val;
        dp[0][0] = 0;
        int total = (1<<n);
        for(int i = 1;i < tail;++i){
            for(int s = 0;s < total;++s){
                dp[i & 1][s] = dp[(i - 1) & 1][s];
                if(depot[i].state != (s & depot[i].state) || dp[(i - 1) & 1][s - depot[i].state] == -1) continue;
                dp[i & 1][s] = max(dp[i & 1][s],dp[(i - 1) & 1][s - depot[i].state] + depot[i].val);
            }
        }
        double ans = 0;
        for(int s = 0;s < total;++s){
            ans = max(ans,dp[(tail - 1) & 1][s]);
        }
        printf("%.2lf
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tiberius/p/9164168.html