4069: [Apio2015]巴厘岛的雕塑 DP+按位贪心

本文分享了一道涉及位运算和动态规划的编程题目解题思路。通过按位贪心算法,作者实现了高效的求解过程,并针对不同子任务提出了特定策略。文章提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

去年的我对位运算一无所知。。所以在考场上直接没敢看题。。之后据说搜索有分,错的DP有分。我的内心是崩溃的。。然而就算看了题还是什么都不会写


考虑按位贪心,从高位到低位枚举,用fi,j表示前i个数分成j段且保证满足已经枚举过的位的答案。
然后O(n3)就可以轻松过点前4Subtask
对于第5Subtask,满足A=1,所以我们用gi表示前i个数满足答案的情况下最少分成几段,只要保证gn<=B就可以了。
时隔半年多看这道题感觉还是挺水的嘛

#include<iostream>
#include<cstdio>
#define ll long long 
using namespace std;
ll s[2005],ans;
int n,a,b,B;
int g[2005],f[105][105];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool pd(ll t)
{
    return (((t>>B+1)|ans)==ans&&(t>>B&1)==0);
}
int main()
{
    n=read(); a=read(); b=read();
    for (int i=1;i<=n;i++) s[i]=s[i-1]+read();
    for (;1ll<<B<s[n];B++);
    if (a!=1)
    {
        f[0][0]=1;
        for (;~B;B--)
        {
            for (int i=1;i<=n;i++)
                for (int j=1;j<=min(i,b);j++)
                {
                    f[i][j]=0;
                    for (int k=0;k<i&&!f[i][j];k++)
                        if (f[k][j-1]&&pd(s[i]-s[k])) f[i][j]=1;
                }
            int tmp=1;
            for (int i=a;i<=b&&tmp;i++)
                if (f[n][i]) tmp=0;
            ans=ans<<1|tmp;
        }
    }
    else
    {
        for (;~B;B--)
        {
            for (int i=1;i<=n;i++)
            {
                g[i]=n+1;
                for (int k=0;k<i;k++)
                    if (pd(s[i]-s[k])) g[i]=min(g[i],g[k]+1);
            }
            ans=ans<<1|(g[n]>b);
        }
    }
    cout << ans << endl;        
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值