POJ 1321 棋盘问题(DFS & 状压DP)

    用DFS写当然很简单了,8!的复杂度,16MS搞定。

    在Discuss里看到有同学用状态压缩DP来写,就学习了一下,果然很精妙呀。

    状态转移分两种,当前行不加棋子,和加棋子。dp[i][j]中,i代表行数,j代表当前行棋子的状态。j的二进制中,1代表有旗子,0代表无棋子。

    贴代码~状压DP果然快一点。

#include <cstdio>

#include <cstring>



int n,k,count;

bool mp[10][10];

int num[256];

int dp[9][256];



int main()

{

//    freopen("in.txt","r",stdin);



    for(int i=1;i<256;i++)

    {

        int tmp=i;

        while(tmp)

        {

            if(tmp&1)

                num[i]++;

            tmp>>=1;

        }

    }



    while(~scanf("%d%d",&n,&k) && n!=-1 && k!=-1)

    {

        char str[20];

        for(int i=1;i<=n;i++)

        {

            scanf("%s",str+1);

            for(int l=1;l<=n;l++)

            {

                if(str[l]=='#')

                    mp[i][l]=true;

                else

                    mp[i][l]=false;

            }

        }



        int status=1<<n;



        memset(dp,0,sizeof(dp));

        dp[0][0]=1;

        for(int i=1;i<=n;i++)

        {

            for(int j=0;j<status;j++) if(num[j]<=k)

            {

                dp[i][j]+=dp[i-1][j];

                for(int l=1;l<=n;l++) if(mp[i][l] && (j&(1<<(l-1)))==0)

                {

                    dp[i][(j|(1<<(l-1)))]+=dp[i-1][j];

                }

            }

        }



        int ans=0;

        for(int i=0;i<status;i++) if(num[i]==k)

            ans+=dp[n][i];



        printf("%d\n",ans);

    }

}

    还有传统的DFS……

#include <cstdio>

#include <cstring>



int n,k,count;

bool mp[10][10];

bool col[10];



void DFS(int x,int rest)

{

    if(rest==0)

    {

        count++;

        return;

    }

    if(x>n)

        return;

    for(int i=1;i<=n;i++) if(!col[i] && mp[x][i])

    {

        col[i]=true;

        DFS(x+1,rest-1);

        col[i]=false;

    }

    if(rest+x<=n)

        DFS(x+1,rest);

}



int main()

{

//  freopen("in.txt","r",stdin);

    while(~scanf("%d%d",&n,&k) && n!=-1 && k!=-1)

    {

        memset(col,0,sizeof(col));

        char str[20];

        for(int i=1;i<=n;i++)

        {

            scanf("%s",str+1);

            for(int k=1;k<=n;k++)

            {

                if(str[k]=='#')

                    mp[i][k]=true;

                else

                    mp[i][k]=false;

            }

        }



        count=0;

        DFS(1,k);

        printf("%d\n",count);

    }

}

 

你可能感兴趣的:(poj)