• P5074 Eat the Trees


    思路

    同样是插头DP,但是这题因为可以形成多个回路,所以左右括号是没有区别的,只需要01就可以表示了
    注意if的嵌套关系
    注意全零矩阵也要输出1

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define int long long
    using namespace std;
    const int HASHsize = 400000;
    int mat[20][20],n,m,T,pos[40];
    int cnt[2],now,last,ans,endx,endy,fir[HASHsize+10],nxt[HASHsize+10],val[2][HASHsize+10],times[2][HASHsize+10];
    void init(void){
        memset(mat,0,sizeof(mat));
        memset(cnt,0,sizeof(cnt));
        now=0,last=0,ans=0,endx=0,endy=0;
        memset(fir,0,sizeof(fir));
        memset(nxt,0,sizeof(nxt));
        memset(val,0,sizeof(val));
        memset(times,0,sizeof(times));
    }
    void insert(int c,int num){
        int t=c%HASHsize;
        for(int i=fir[t];i;i=nxt[i]){
            if(val[now][i]==c){
                times[now][i]+=num;
                return;
            }
        }
        ++cnt[now];
        val[now][cnt[now]]=c;
        times[now][cnt[now]]=num;
        nxt[cnt[now]]=fir[t];
        fir[t]=cnt[now];
    }
    void print(int x){
        for(int i=0;i<m+1;i++)
            printf("%lld",(x>>i)&1);
        printf("
    ");
    }
    void dp(void){
        now=0;
        insert(0,1);
        for(int i=1;i<=n;i++){
            for(int k=1;k<=cnt[now];k++)
                val[now][k]<<=1;
            for(int j=1;j<=m;j++){
                last=now;
                now^=1;
                cnt[now]=0;
                memset(fir,0,sizeof(fir));
                memset(nxt,0,sizeof(nxt));
                // printf("i=%lld j=%lld
    ",i,j);
                for(int k=1;k<=cnt[last];k++){
                    int state=val[last][k],num=times[last][k],plugL=(state>>(j-1))&1,plugU=(state>>(j))&1;
                    // printf("num=%lld
    ",num);
                    // print(state);
                    // printf("plugL=%lld plugU=%lld
    ",plugL,plugU);
                    if(mat[i][j]){
                        //新建连通分量
                        if((!plugL)&&(!plugU)){
                            if(mat[i+1][j]&&mat[i][j+1])
                                insert(state+(1<<(j-1))+(1<<(j)),num);
                        }
                        //合并联通分量
                        else if(plugL&&plugU){
                            if(i==endx&&j==endy)
                                ans+=num;
                            else
                                insert(state-(1<<(j-1))-(1<<(j)),num);
                        }
                        //延续联通分量
                        else{
                            if(plugL){
                                // printf("!
    ");
                                if(mat[i+1][j])
                                    insert(state,num);
                                if(mat[i][j+1])
                                    insert(state-(1<<(j-1))+(1<<(j)),num);
                            }
                            if(plugU){
                                if(mat[i+1][j])
                                    insert(state-(1<<(j))+(1<<(j-1)),num);
                                if(mat[i][j+1])
                                    insert(state,num);
                            }
                        }
                    }
                    else{
                        if((!plugL)&&(!plugU))
                            insert(state,num);
                    }
                }
            }
        }
    }
    signed main(){
        scanf("%lld",&T);
        pos[0]=1;
        for(int i=1;i<30;i++)
            pos[i]=pos[i-1]<<1;
        while(T--){
            bool isok=true;
            init();
            scanf("%lld %lld",&n,&m);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++){
                    scanf("%lld",&mat[i][j]);
                    if(mat[i][j]){
                        endx=i;endy=j;
                        isok=false;
                    } 
                }
            // printf("endx=%lld endy=%lld
    ",endx,endy);
            if(!isok){
                dp();
                printf("%lld
    ",ans);
            }
            else{
                printf("1
    ");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    SQL SERVER CXPACKET-Parallelism Wait Type 的惯用解决方案
    服务器主体 "sa" 无法在当前安全上下文下访问数据库 XXX[SQLSTATE 08004] (错误 916). 该步骤失败。
    Android 使用 aapt 命令查看 apk 包名
    Android数据库GreenDao的使用总结
    NestedScrollView、ScrollView 加载完自动滑动至底部问题的解决方案
    Android框架式编程之Retrofit
    Visual Studio 开发(三):Visual Studio 使用时常见问题解决方案
    Android 网络交互之移动端与服务端的加密处理
    Android框架式编程之ViewModel
    Android框架式编程之LiveData
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10839614.html
Copyright © 2020-2023  润新知