[状压DP][DFS]JZOJ 2679 跨时代
Posted mastervan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[状压DP][DFS]JZOJ 2679 跨时代相关的知识,希望对你有一定的参考价值。
分析
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);
以上是关于[状压DP][DFS]JZOJ 2679 跨时代的主要内容,如果未能解决你的问题,请参考以下文章
jzoj5990. 北大2019冬令营模拟2019.1.6Bear (状压dp)
Atcoder Beginner Contest152F(DFS+状压DP)