1 条题解

  • 1
    @ 2022-8-29 9:47:18
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define hash deep_dark_fantasy
    #define inf 1e9
    using namespace std;
    inline int read(){
        int re=0,flag=1;char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-') flag=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
        return re*flag;
    }
    int n,m,x[150][150],cur,pre,ex,ey;
    int st[2][300010];ll ans[2][300010],re;
    int tot[2],bit[20],state[300010],st_tot,hash=300000;
    struct edge{
        int to,next;
    }a[300010];
    void insert(int sta,ll val){//往哈希表里插入一个状态,顺便更新答案
        int p=sta%hash,i;
        for(i=state[p];i;i=a[i].next){
            if(st[cur][a[i].to]==sta){
                ans[cur][a[i].to]=max(ans[cur][a[i].to],val);return;
            }
        }
        tot[cur]++;
        a[++st_tot].to=tot[cur];
        a[st_tot].next=state[p];
        state[p]=st_tot;st[cur][tot[cur]]=sta;ans[cur][tot[cur]]=val;
    }
    void dp(){
        int i,j,k,l,now,down,right;ll val;re=-inf;
        cur=0;tot[cur]=1;ans[cur][1]=0;st[cur][1]=0;
        for(i=1;i<=n;i++){
            for(j=1;j<=tot[cur];j++) st[cur][j]<<=2;
            for(j=1;j<=m;j++){
                pre=cur;cur^=1;tot[cur]=0;st_tot=0;memset(state,0,sizeof(state));
                for(k=1;k<=tot[pre];k++){
                    now=st[pre][k];val=ans[pre][k];
                    right=(now>>bit[j-1])%4;down=(now>>bit[j])%4;
                    if(!down&&!right){//新建联通分量,加一个下插头一个右插头
                        insert(now,val);
                        if(j!=m) 
                            insert(now+(1<<bit[j-1])+((1<<bit[j])<<1),val+x[i][j]);
                    }
                    if(down&&!right){//延续下插头
                        insert(now-down*(1<<bit[j])+down*(1<<bit[j-1]),val+x[i][j]);
                        if(j!=m)insert(now,val+x[i][j]);
                    }
                    if(right&&!down){//延续右插头
                        insert(now,val+x[i][j]);
                        if(j!=m) 
                            insert(now+right*(1<<bit[j])-right*(1<<bit[j-1]),val+x[i][j]);
                    }
                    if(right==1&&down==1){//合并两个左括号
                        int cnt=1;
                        for(l=j+1;l<=m;l++){
                            if((now>>bit[l])%4==1) cnt++;
                            if((now>>bit[l])%4==2) cnt--;
                            if(!cnt){
                                insert(now-(1<<bit[l])-(1<<bit[j])-(1<<bit[j-1]),val+x[i][j]);
                                break;
                            }
                        }
                    }
                    if(right==2&&down==2){//合并两个右括号
                        int cnt=1;
                        for(l=j-2;l>=0;l--){
                            if((now>>bit[l])%4==1) cnt--;
                            if((now>>bit[l])%4==2) cnt++;
                            if(!cnt){
                                insert(now+(1<<bit[l])-((1<<bit[j])<<1)-((1<<bit[j-1])<<1),val+x[i][j]);
                                break;
                            }
                        }
                    }
                    if(right==2&&down==1){//合并)(
                        insert(now-((1<<bit[j-1])<<1)-(1<<bit[j]),val+x[i][j]);
                    }
                    if(right==1&&down==2){//合并(),统计答案
                        if((now==(1<<bit[j-1])+((1<<bit[j])<<1))&&(val+x[i][j]>re)){
                            re=val+x[i][j];
                        }
                    }
                }
            }
        }
    }
    int main(){
        int i,j;
        n=read();m=read();
        for(i=1;i<=10;i++) bit[i]=(i<<1);
        for(i=1;i<=n;i++) for(j=1;j<=m;j++) x[i][j]=read();
        dp();
        printf("%lld",re);
    }
    
    • 1

    信息

    ID
    1187
    时间
    909ms
    内存
    162MiB
    难度
    7
    标签
    (无)
    递交数
    25
    已通过
    8
    上传者