• [HNOI2007]神奇游乐园(插头DP)


    题意:n*m的矩阵内值有正有负,找一个四连通的简单环(长度>=4),使得环上值的和最大。

    题解:看到2<=m<=6和简单环,很容易想到插头DP,设f[i][j][k]表示轮廓线为第i行第j列,插头状态为k的最大满意度。然后又成了一道插头DP的板子题。注意左插头为左括号,上插头为右括号,其余位置无插头,因为题目不要求走遍所有格子,且只能走一条回路。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=11000,mod=10007;
    int n,m,ans,p,bin[12],w[110][10],a[2][N],f[2][N],tot[N],hd[N],nxt[N];
    void add(int S,int v)
    {
        int u=S%mod;
        for(int i=hd[u];i;i=nxt[i])if(a[p][i]==S){f[p][i]=max(f[p][i],v);return;}
        a[p][++tot[p]]=S,nxt[tot[p]]=hd[u],hd[u]=tot[p],f[p][tot[p]]=v;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        ans=-1e9;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        scanf("%d",&w[i][j]);
        bin[0]=1;for(int i=1;i<=10;i++)bin[i]=bin[i-1]<<2;
        tot[p]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=tot[p];j++)a[p][j]<<=2;
            for(int j=1;j<=m;j++)
            {
                p^=1;
                memset(hd,0,sizeof hd);
                tot[p]=0;
                for(int k=1;k<=tot[p^1];k++)
                {
                    int S=a[p^1][k],b1=(S>>j*2-2)%4,b2=(S>>j*2)%4,val=f[p^1][k];
                    if(!b1&&!b2)
                    {
                        if(i<n&&j<m)add(S+bin[j-1]+2*bin[j],val+w[i][j]);
                        add(S,val);
                    }
                    else if(!b1&&b2)
                    {
                        if(j<m)add(S,val+w[i][j]);
                        if(i<n)add(S-b2*bin[j]+b2*bin[j-1],val+w[i][j]);
                    }
                    else if(b1&&!b2)
                    {
                        if(j<m)add(S-b1*bin[j-1]+b1*bin[j],val+w[i][j]);
                        if(i<n)add(S,val+w[i][j]);
                    }
                    else if(b1==1&&b2==1)
                    {
                        int k1=1;
                        for(int t=j+1;t<=m;++t)
                        {
                            if((S>>t*2)%4==1)k1++;
                            if((S>>t*2)%4==2)k1--;
                            if(!k1){add(S-bin[j-1]-bin[j]-bin[t],val+w[i][j]);break;}
                        }
                    }
                    else if(b1==2&&b2==2)
                    {
                        int k1=1;
                        for(int t=j-2;t>=0;--t)
                        {
                            if((S>>t*2)%4==1)k1--;
                            if((S>>t*2)%4==2)k1++;
                            if(!k1){add(S-2*bin[j-1]-2*bin[j]+bin[t],val+w[i][j]);break;}
                        }
                    }
                    else if(b1==2&&b2==1)add(S-2*bin[j-1]-bin[j],val+w[i][j]);
                    else if(S-bin[j-1]-2*bin[j]==0)ans=max(ans,val+w[i][j]);
                }
            }
        }
        printf("%d",ans);
    }
    View Code
  • 相关阅读:
    第五周日志模块正则和包
    tcpdump常用参数说明
    Python调用API接口的几种方式 数据库 脚本
    关于相互递归调用
    VS Code中配置Markdown
    2019CCPC网络赛 HD6707——杜教筛
    一个关于gcd的等式的证明
    2019CCPC网络赛 HDU 6702——找规律
    双系统的安装与卸载
    [0, 1] 区间内 n 次独立随机事件的一些问题
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10780704.html
Copyright © 2020-2023  润新知