• HDU1693 Eat the Trees


    题目

    插头dp,由于我们不需要判断曼哈段回路是否提前闭合,所以并不要括号序列,直接二进制状压一条轮廓线即可, (1)表示这个位置有插头,(0)表示没有

    在考虑到((i,j))我们考虑一下((i,j-1))是否有向右的插头,((i-1,j))是否有向下的插头

    之后转移可以大力讨论一波

    右没有下没有,那么必须在((i,j))建一个转角,在((i,j))新建一个向右和向下的插头

    右有下有,那么必须在((i,j))处闭合,于是在((i,j))新建一个向左和向上的插头,和原来的插头连接

    右有下没有,先新建一个向左的插头,之后可以再来一个向右的插头,或者转向一下建一个向下的插头

    右没有下有,先新建一个向下的插头,之后可以再来一个向下的插头,或者转向一下建一个向右的插头

    转移的时候考虑新建插头对轮廓线的影响就好了

    代码

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    int a[13][13],len,T;
    LL dp[2][(1<<13)+1];
    inline void upd(int &val,int pos,int v){--pos;val&=(len^(1<<pos));val|=(v<<pos);}
    inline void solve() {
    	int n,m;scanf("%d%d",&n,&m);len=(1<<(m+1))-1;
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=m;j++) scanf("%d",&a[i][j]);
    	int o=0;memset(dp,0,sizeof(dp));dp[0][0]=1;
    	for(re int i=1;i<=n;i++) {
    		for(re int j=1;j<=m;j++) {
    			memset(dp[o^1],0,sizeof(dp[o^1]));
    			for(re int cur,k=0;k<=len;++k) {
    				if(!dp[o][k]) continue;
    				int left=k>>(j-1)&1,up=k>>j&1;
    				if(!a[i][j]) {
    					if(!left&&!up) dp[o^1][k]+=dp[o][k];
    					continue;
    				}
    				if(!left&&!up) cur=k,upd(cur,j,1),upd(cur,j+1,1),dp[o^1][cur]+=dp[o][k];
    				if(left&&up) cur=k,upd(cur,j,0),upd(cur,j+1,0),dp[o^1][cur]+=dp[o][k];
    				if(left^up) {
    					cur=k;upd(cur,j,0),upd(cur,j+1,1);dp[o^1][cur]+=dp[o][k];
    					cur=k;upd(cur,j,1),upd(cur,j+1,0);dp[o^1][cur]+=dp[o][k];
    				}
    			}
    			o^=1;
    		}
    		for(re int j=(1<<m)-1;j>=0;--j) dp[o][j<<1]=dp[o][j];
    		for(re int j=0;j<=len;j++) if(j&1) dp[o][j]=0;
    	}
    	printf("%lld
    ",dp[o][0]);
    }
    int main() {scanf("%d",&T);while(T--) solve();return 0;}
    
  • 相关阅读:
    linux cmake安装方法
    Linux下安装numpy
    linux下安装opencv3.0
    linux升级gcc
    php session获取不到的解决方法
    python Tesseract安装方法
    SQLite-编译指示
    第十章:定积分
    7. 错误、调试和测试
    钱纳里的工业化阶段理论
  • 原文地址:https://www.cnblogs.com/asuldb/p/12106442.html
Copyright © 2020-2023  润新知