• 拯救莫莉斯 状压dp


    题目大意:每个点有费用,要求选出花费最少的一些点,使得全部点都满足:他被选或与他相邻的任意点被选。

    没看清数据范围233333

    和翻格子游戏一样,考虑上中下三行,可行才能转移

    f[i][j][k]表示到第i行i-1行状态为j,i行状态为k,且i行以前的所有行均满足条件

    f[i][j][k]------>f[i+1][k][l]  j|k|l|(k<<1)|(k>>1) 覆盖所有棋子

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 55
    using namespace std;
    int a[N][N],cost[N][257],f[N][257][257],g[N][257][257],ans,tot,n,m;
    int bit[10];
    int getnum(int x){
        int nn=0;
        while(x){nn+=x&1;x>>=1;}
        return nn;
    }
    int main()
    {
        ans=0x7ffff; tot=0x7ffff;
        memset(f,0x3f,sizeof f);
        memset(g,0x3f,sizeof g);
        bit[0]=1; for(int i=1;i<=8;i++)bit[i]=bit[i-1]<<1;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
            for(int j=0;j<(1<<m);j++)
                for(int k=1;k<=m;k++)
                    if(j&bit[k-1]) cost[i][j]+=a[i][k];
        }
        for(int i=0;i<(1<<m);i++){
            f[1][0][i]=cost[1][i];
            g[1][0][i]=getnum(i);
        }
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<(1<<m);j++)
                for(int k=0;k<(1<<m);k++)
                    for(int l=0;l<(1<<m);l++){
                        if((((j)|(k)|(l)|(k<<1)|(k>>1))&(bit[m]-1))<(bit[m]-1))continue;
                        if((f[i-1][j][k]+cost[i][l]<f[i][k][l])||((f[i-1][j][k]+cost[i][l]==f[i][k][l])&&(g[i-1][j][k]+getnum(l)<g[i][k][l]))){
                            f[i][k][l]=f[i-1][j][k]+cost[i][l];
                            g[i][k][l]=g[i-1][j][k]+getnum(l);
                        }
                    }
            if(i==n){
                for(int j=0;j<(1<<m);j++)
                    for(int k=0;k<(1<<m);k++){
                        if((((j)|(k)|(k<<1)|(k>>1))&(bit[m]-1))<(bit[m]-1))continue;
                        if(f[i][j][k]<ans||(f[i][j][k]==ans&&g[i][j][k]<tot)){
                            ans=f[i][j][k];
                            tot=g[i][j][k];
                        }
                    }
            }
        }
        printf("%d %d
    ",tot,ans);
        return 0;
    }


  • 相关阅读:
    20200601:百万级int数据量的一个array求和。
    20200602:千万级数据量的list找一个数据。
    20200531:假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?
    20200530:主从数据库不一致如何解决?
    [USACO06DEC]Milk Patterns G
    [HAOI2016]找相同字符
    [AHOI2013]差异
    [SCOI2012]喵星球上的点名
    [APIO2014]回文串
    [TJOI2015]弦论
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/7746716.html
Copyright © 2020-2023  润新知