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);
    }
}

 

posted @ 2013-08-01 21:20  SF-_-  阅读(1906)  评论(0编辑  收藏  举报