zoukankan      html  css  js  c++  java
  • BZOJ 4565 状压DP

    思路:

    f[i][j][S]表示从i到j压成S状态

    j-m是k-1的倍数

    $f[i][j][S<<1]=max(f[i][j][S<<1],f[i][m-1][S]+f[m][j][0]),$
    $f[i][j][S<<1|1]=max(f[i][j][S<<1|1],f[i][m-1][S]+f[m][j][1]);$


    为了区分001 01 和1

    更新的时候要新开一个数组记录 最后再更新

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define int long long
    int n,k,f[333][333][256],g[2],ans,c[333],w[333];
    char s[333];
    signed main(){
        scanf("%lld%lld",&n,&k);
        scanf("%s",s+1);
        for(int i=0;i<(1<<k);i++)scanf("%lld%lld",&c[i],&w[i]);
        memset(f,0xcf,sizeof(f));
        for(int i=1;i<=n;i++)s[i]-='0',f[i][i][s[i]]=0;
        for(int l=2;l<=n;l++)
            for(int i=1;i<=n-l+1;i++){
                int j=i+l-1,len=j-i;
                while(len>=k)len-=k-1;
                for(int m=j;m>i;m-=k-1)
                    for(int S=0;S<(1<<len);S++)
                        f[i][j][S<<1]=max(f[i][j][S<<1],f[i][m-1][S]+f[m][j][0]),
                        f[i][j][S<<1|1]=max(f[i][j][S<<1|1],f[i][m-1][S]+f[m][j][1]);
                if(len==k-1){
                    g[0]=g[1]=-100000000000000ll;
                    for(int S=0;S<(1<<k);S++)
                        g[c[S]]=max(g[c[S]],f[i][j][S]+w[S]);
                    f[i][j][0]=g[0],f[i][j][1]=g[1];
                }
            }
        for(int i=0;i<(1<<k);i++)ans=max(ans,f[1][n][i]);
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    栈实现队列
    朋友圈的数量
    岛屿的数量
    岛屿的最大面积
    单词最短路径
    矩阵中查找单词
    拨号问题
    CDN原理
    TCP建立连接的三次握手过程
    JavaScript手写几种常见的排序算法:冒泡、选择、插入、希尔、归并、快排
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6654390.html
Copyright © 2011-2022 走看看