BZOJ 4007 [JLOI2015]战争调度

树形DP+状压+搜索。

刚开始想了一些奇怪的树形DP,都没法做,后来发现是自己对题目理解有误

如果枚举所有点的决策,那是 O(22n) 。发现对于一个最底层节点,他的贡献只和一条链有关,于是可以考虑从这里下手。

iDFSDPf[i][j]ijf[i][j]=max(f[i2][a]+f[i2+1][b])(a+b=j)

n±1O(2n)nO(n(2n)2)O(n)O(2nn(2n)2+2nn)O(2nn)

这里有详细估计复杂度(Orz):http://blog.csdn.net/vmurder/article/details/45146301

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 2100
#define C 12
using namespace std;
int n, m, w[N][C], g[N][C], f[N][N];
void dfs(int x, int sta, int d)
{
    memset(f[x],0,sizeof(f[x]));
    if(d==n)
    {
        f[x][1]=f[x][0]=0;
        for(int j = 1; j < n; j++, sta>>=1)
        {
            if(sta&1)f[x][1]+=w[x][j];
            else f[x][0]+=g[x][j];
        }
        return;
    }
    dfs(x<<1,sta<<1,d+1);
    dfs(x<<1|1,sta<<1,d+1);
    for(int i = 0, ii = 1<<(n-d-1); i <= ii; i++)
        for(int j = 0, jj = 1<<(n-d-1); j <= jj; j++)
            f[x][i+j]=max(f[x][i+j],f[x<<1][i]+f[x<<1|1][j]);
    dfs(x<<1,sta<<1|1,d+1);
    dfs(x<<1|1,sta<<1|1,d+1);
    for(int i = 0, ii = 1<<(n-d-1); i <= ii; i++)
        for(int j = 0, jj = 1<<(n-d-1); j <= jj; j++)
            f[x][i+j]=max(f[x][i+j],f[x<<1][i]+f[x<<1|1][j]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1<<(n-1), ii=(1<<n)-1; i <= ii; i++)
        for(int j = 1; j < n; j++)
            scanf("%d",&w[i][j]);
    for(int i = 1<<(n-1), ii=(1<<n)-1; i <= ii; i++)
        for(int j = 1; j < n; j++)
            scanf("%d",&g[i][j]);
    dfs(1,0,1);
    int ans=0;
    for(int i = 0; i <= m; i++)
        ans=max(ans,f[1][i]);
    printf("%d\n",ans);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值