【TopCoderSRM318Div1 900】BiggestRectangleHard

Problem Statement

Little Josh has found several sticks of various lengths. He wants to form a rectangle with the biggest possible area, using these sticks as the perimeter. He is allowed to glue sticks together, but he is not allowed to break single sticks into multiple shorter sticks. Sticks may only be glued together at their endpoints, so a stick of length 2 and a stick of length 3 can only be glued together to form a stick of length 5.
For example, if Josh has sticks with lengths {1, 3, 3, 4, 5, 7}, he can create a 3 x 5 rectangle using the two sticks of length 3, the stick of length 5, and the sticks of lengths 1 and 4 glued together. This rectangle has an area of 15 square inches, which is the biggest area that can be achieved with these sticks.
You will be given a vector lengths containing the lengths of the sticks in inches. Return the maximal area (in square inches) of a rectangle that can be created using these sticks. If it is impossible to form a rectangle, return -1.

给定n(4<=n<=16)个火柴棍,求能拼出的最大面积的矩形的面积.如拼不成任何矩形,输出-1.

又是状压DP…
能拼成矩形的条件是,用来拼长和宽的木棒必须能分成两个长度和相等的子集,所以预处理某个子集能不能分成两个相等子集,然后分别枚举合法的长宽集合,计算面积.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<queue>
#include<map>
using namespace std;
class BiggestRectangleHard
{
    public:

    int findArea(vector<int> lengths)
    {
        int n=lengths.size(),ret=-1;
        vector<int> sum(1<<n,0),g(1<<n,0);
        for (int i=0;i<(1<<n);++i)  for (int j=0;j<n;++j)   if (i&(1<<j))   sum[i]+=lengths[j];
        for (int i=0;i<(1<<n);++i)
        {
            if (sum[i]&1)   continue;
            for (int j=i;j;(--j)&=i)    if (sum[j]<<1==sum[i])  {   g[i]=1;break;   }
        }
        for (int i=0;i<(1<<n);++i)
        {
            if (!g[i])  continue;
            int t=((1<<n)-1)^i;
            for (int j=t;j;(--j)&=t)    if (g[j])   ret=max(ret,sum[i]*sum[j]>>2);
        }
        return ret;
    }
};

你可能感兴趣的:(状压dp)