zoukankan      html  css  js  c++  java
  • HDU4026 Unlock the Cell Phone [状态压缩DP]

      一开始看范围特别小就写搜索了。。。结果自己随便出了个4*4就过不了了。。

      其实就是状态压缩DP,求哈密顿回路要多少条,只是要注意判断两点是否可以划线就可以了。

      

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    typedef __int64 LL;
    int n,m,tot;
    int mz[25],bet[25][25][25],full;
    int zero[16],zeros,hzero[25],lowb[65536];
    LL d[16][65536],ans;
    int cant(int st,int en,int stat){
        st=zero[st],en=zero[en];
        if(st>en)std::swap(st,en);
        for(int i=1;i<=bet[st][en][0];i++){
            int x=bet[st][en][i];
            if(mz[x]==1)return 1;
            if(mz[x]==0&&((stat>>hzero[x])&1)==0)return 1;
        }
        return 0;
    }
    LL dp(int last,int stat){
        if(d[last][stat]!=-1)return d[last][stat];
        if(stat==(stat&-stat))return 1;
        LL nans=0;
        int nstat=stat,now,i;
        while(nstat){
            now=(nstat&-nstat),i=lowb[now],nstat-=now;;
            if(i==last||cant(i,last,stat))continue;
            nans+=dp(i,stat&~(1<<last));
        }
        return d[last][stat]=nans;
    }
    int between(int k,int i,int j,int n,int m){
        int xk=k/m,yk=k%m,xi=i/m,yi=i%m,xj=j/m,yj=j%m;
        if((xk-xi)*(xk-xj)<=0&&(yk-yi)*(yk-yj)<=0){
            if((yj-yi)*(xk-xi)==(xj-xi)*(yk-yi))return 1;
        }
        return 0;
    }
    void init(int n,int m){
        for(int i=0;i<tot;i++){
            for(int j=i+1;j<tot;j++){
                int &x=bet[i][j][0];x=0;
                for(int k=i+1;k<j;k++){
                    if(between(k,i,j,n,m))x++,bet[i][j][x]=k;
                }
            }
        }
        for(int i=0,x=1;i<16;i++,x<<=1)lowb[x]=i;
    }
    int main(){
      //  freopen("test.in","r",stdin);
        while(scanf("%d%d",&n,&m)!=EOF){
            ans=0,tot=n*m,zeros=0;
            init(n,m);
            for(int i=0;i<tot;i++){
                scanf("%d",&mz[i]);
                if(mz[i]==0)hzero[i]=zeros,zero[zeros++]=i;
            }
            full=(1<<zeros)-1;
            for(int i=0;i<zeros;i++)for(int j=0;j<=full;j++)d[i][j]=-1;
            for(int i=0;i<zeros;i++)ans+=dp(i,full);
            printf("%I64d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 2038: [2009国家集训队]小Z的袜子 (莫队)
    codevs 3981 动态最大子段和(线段树)
    ACM北大暑期课培训第八天
    ACM北大暑期课培训第七天
    ACM北大暑期课培训第六天
    ACM北大暑期课培训第五天
    ACM北大暑期课培训第四天
    HDU4403-模拟、数学
    HDU4296-ChengduOnling-贪心
    POJ3176-基础DP
  • 原文地址:https://www.cnblogs.com/swm8023/p/2659375.html
Copyright © 2011-2022 走看看