码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2064: 分裂 [DP 状压 转化]

时间:2017-03-07 09:06:15      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:logs   .com   owb   const   printf   集合   问题   iostream   geo   

传送门

题意:一开始$n$块面积最后$m$块面积,面积和相等每次可以分裂或者合并,问最少几次


 

昨天忘发了...

不会....

考虑最差情况,$n+m-2$所有先合并再分裂

发现只有当前后两个子集相等时可以变成对方

如果前后能分成$k$堆对应相等,次数就是$n+m-2*k$

问题就是求前后各能分成几堆面积相等

 

混在一起,后面的面积改为负

$f[i]$表示选了集合$i$里的土地,能分成几个互不相交的权值为$0$的子集

$f[i]=max{f[i^(1<<j)]}+ sum[i]==0 $

因为$0-0=0$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=(1<<20)+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
 
int n,m,f[N],sum[N],All;
int main(){
    //freopen("in","r",stdin);
    n=read();
    for(int i=0;i<n;i++) sum[1<<i]=read();
    m=read();
    for(int i=n;i<n+m;i++) sum[1<<i]=-read();
    All=1<<(n+m);
    for(int i=1;i<All;i++){
        int lowbit=i&-i;
        sum[i]=sum[i-lowbit]+sum[lowbit];
        for(int j=0;j<n+m;j++) 
            if(i&(1<<(j-1))) f[i]=max(f[i],f[i-(1<<(j-1))]);
        f[i]+= sum[i]==0;
    }
    printf("%d",n+m-2*f[All-1]);
}

 

BZOJ 2064: 分裂 [DP 状压 转化]

标签:logs   .com   owb   const   printf   集合   问题   iostream   geo   

原文地址:http://www.cnblogs.com/candy99/p/6512874.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!