分析
n的大小提示我们使用状压
那么我们设f[i]表示i中的边全部选上后,有无组合能够达到总长度的一半
这个是比较简单的DP过程
然后DFS,记录两根长的和和两根宽的和,以及选边的状态,最后判断能否分成一半即可
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; int n,mxb,l[16],f[1<<16]; bool b[500]; int cnt,ans; void Calc(int S,int s) { if (s&1) return; memset(b,0,sizeof b);b[0]=1; for (int i=0;i<n;i++) { if (S<(1<<i)) break; if (S&(1<<i)) for (int j=s;j-l[i]+1;j--) b[j]|=b[j-l[i]]; } if (b[s>>1]) f[S]=1; } void DFS(int dep=0,int sa=0,int sb=0,int a=0,int b=0) { if (dep==n) { if (f[sa]&&f[sb]) ans=max(ans,a*b>>2); return; } DFS(dep+1,sa,sb,a,b); DFS(dep+1,sa|(1<<dep),sb,a+l[dep],b); DFS(dep+1,sa,sb|(1<<dep),a,b+l[dep]); } int main() { scanf("%d",&n);mxb=1<<n; for (int i=0;i<n;i++) scanf("%d",&l[i]); for (int i=0;i<mxb;i++) { cnt=0; for (int j=0;j<n;j++) cnt+=l[j]*((i&(1<<j))>0); Calc(i,cnt); } DFS(); printf((ans?"%d":"No Solution"),ans); }