[BZOJ4069]-[Apio2015]巴厘岛的雕塑-位运算的贪心dp

11人阅读 评论(0) 收藏 举报
分类:

说在前面

并没有什么想说的,但是要保持格式


题目

BZOJ4069传送门 这是个权限题
洛谷P3646传送门

题面就不概括了…subtask略多可以去看看


解法

首先这个题询问的是最小值,于是me一开始想到二分答案,然而并不具有连续性。如果用小于等于答案去二分,check又很麻烦
于是这个时候就要坚定一种信念!位运算是相互独立的,因此应该可以从高到低贪心的确定答案

对于那些N100的数据,明显是可以接受N3log的算法。于是我们可以这么定义:dp[i][j]表示前i个分了j组,并且每一个分组的高位与已经确定的ans相符,且当前待确定位为0,是否有一种合法方案。转移很简单。最后只需要看一看dp[N][A...B]中是否有一个为true就可以了

然而最后一个点N2000,并不能这样做。不过它有一个特殊性质,就是A=1,也就是说只要不超出分组上限就好了。因为没有下限,所以这个东西具有最优决策。定义dp[i]表示,前i个(条件和上面一样),最少分多少组。如果dp[N]B说明当前选0可行


下面是自带大常数的代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

int N , A , B ;
long long a[2005] , sum[2005] , ans ;

int g[2005] ;
bool checkSpe( int x ){
    memset( g , 0x3f , sizeof( g ) ) ; g[0] = 0 ;
    long long tmp , ww = 1LL << ( x - 1 ) ;
    for( int i = 1 ; i <= N ; i ++ ){
        for( int j = 0 ; j < i ; j ++ ){
            tmp = sum[i] - sum[j] ;
            if( ( ( tmp >> x ) | ( ans >> x ) ) != ( ans >> x ) ) continue ;
            if( !( tmp & ww ) && g[i] > g[j] )
                g[i] = g[j] + 1 ;
        }
    } return g[N] <= B ;
}

bool dp[105][105] ;
bool check( int x ){
    memset( dp , 0 , sizeof( dp ) ) ;
    dp[0][0] = true ;
    long long tmp , ww = 1LL << ( x - 1 ) ;
    for( int k = 1 ; k <= B ; k ++ ){
        for( int i = 1 ; i <= N ; i ++ ){
            for( int j = 0 ; j < i ; j ++ ){
                tmp = sum[i] - sum[j] ;
                if( ( ( tmp >> x ) | ( ans >> x ) ) != ( ans >> x ) ) continue ;
                if( !( tmp & ww ) && dp[k-1][j] ){
                    dp[k][i] = true ; break ;
                }
            }
        }
        if( k >= A && dp[k][N] ) return true ;
    } return false ;
}

void solve(){
    for( int i = 40 ; i >= 0 ; i -- )
        if( A == 1 ) ans += checkSpe( i + 1 ) ? 0 : ( 1LL << i ) ;
        else ans += check( i + 1 ) ? 0 : ( 1LL << i ) ;
    printf( "%lld" , ans ) ;
}

int main(){
    scanf( "%d%d%d" , &N , &A , &B ) ;
    for( int i = 1 ; i <= N ; i ++ )
        scanf( "%lld" , &a[i] ) , sum[i] = a[i] ;
    for( int i = 1 ; i <= N ; i ++ ) sum[i] += sum[i-1] ;
    solve() ;
}
查看评论

[BZOJ4069][Apio2015]巴厘岛的雕塑(二分+DP)

直接DP不可做(因为按位取或不满足最优化原理)。 而求最大/小与/或/异或和,可以考虑利用二分的思想,在二进制意义下从高到低确定答案的每一位。在此题中要求最小或和,因此从高往低考虑到每一位时,这一位...
  • xyz32768
  • xyz32768
  • 2018-01-20 17:14:20
  • 71

【BZOJ 4069】 [Apio2015]巴厘岛的雕塑

按位贪心+递推/dp~
  • Regina8023
  • Regina8023
  • 2015-05-16 09:10:49
  • 2204

bzoj4069【APIO2015】巴厘岛的雕塑

贪心+DP
  • AaronGZK
  • AaronGZK
  • 2016-04-20 00:30:00
  • 3053

[APIO2015]巴厘岛的雕塑(数位dp)

【题解】 引用ZYF神犇一句话:"显然位运算的极值问题都应该从高位向低位考虑。优先让这一位为0,如果行的话这一位就是0,否则就设为1。"  设答案为ans,从高位到低位枚举 是否有使ans的这...
  • cjk_cjk
  • cjk_cjk
  • 2015-06-12 16:53:29
  • 781

BZOJ4069: [Apio2015]巴厘岛的雕塑

按位贪心,显然较大的位能是0就是0,然后就从高到低枚举每一位。dp判定这一位是否可以填0。 dp[i][j]表示长度为i,分了j段当前位是否可以是0,枚举k转移,如果(s[i]-s[k])这一段这一...
  • MirrorGray
  • MirrorGray
  • 2016-04-27 21:56:11
  • 606

bzoj4069 [Apio2015]巴厘岛的雕塑(贪心+dp+位运算)

把n个数分成k部分,使得每部分的和的按位或最小。我们考虑答案的最大可能值,我们贪心的从高到低枚举二进制下的每一位,为0最好,而为0的条件是要求分成的所有和的这一位上都是0,我们可以用dp去解决这个问题...
  • Icefox_zhx
  • Icefox_zhx
  • 2017-09-22 16:39:28
  • 121

BZOJ4069 [APIO2015]巴厘岛的雕塑

Address 洛谷P3646 BZOJ4069 Solution 按照题意去做发现很不可做。 于是转化一下问题: 我们希望二进制的答案高位尽可能为0,这显然满足最小的性质。 因此贪心地按...
  • bzjr_Log_x
  • bzjr_Log_x
  • 2018-01-21 20:56:57
  • 235

Bzoj4069:[Apio2015]巴厘岛的雕塑:dp+贪心

题目链接:[Apio2015]巴厘岛的雕塑 一开始先写了个既错误又高复杂度的dp,令dp[i][j]=min(dp[i][k],dp[j][k-1]|(s[i]-s[j])),其中s[]代表前缀和 ...
  • qq_34025203
  • qq_34025203
  • 2016-04-25 17:17:18
  • 519

[贪心 DP] BZOJ 4069 [Apio2015]巴厘岛的雕塑

从高位到低位 题目里面数据分两类 一类是A>1,dp一下f[i][j]这段区间是否符合当前答案,n3log; 第二类是A=1,dp一下g[i]表示在满足答案前提下以i为结尾切开来最少能且多少...
  • u014609452
  • u014609452
  • 2016-05-04 21:22:50
  • 335

4069: [Apio2015]巴厘岛的雕塑

4069: [Apio2015]巴厘岛的雕塑 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 344  Solved: 163 [Submit][...
  • CRZbulabula
  • CRZbulabula
  • 2016-12-21 19:51:24
  • 209
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 2177
    排名: 2万+
    博客专栏