POJ 1321 基础搜索 DFS 二

  第二天又写了一个下午的搜索题。愚蠢致死。进一步总结思路。

  POJ 1321 :http://poj.org/problem?id=1321

 

  正确的题意是: 给你矩阵(方形)的边,给你一个 旗子数 k 。 接下来给出由字符 '.' 和 '#’ 的方形矩阵。 要在 '#' 位置放棋子。 请问有几种合法的放置组合方法。不是排列!!

                               合法的放置  题目要求为 :  任何两个旗子不可在同一行同一列。

 

  刚开始的时候没想到一点,所有的位置都会放满。殊不知,按照题目, # 的数目可能会比棋子数多,也可能会少。这么显而易见的题意没有在意,导致后来找bug找到死。

 

  看到题目的第一反应就是,此题和八皇后一个套路。当时在搜索的过程中,判断同行列有无旗子都是傻不拉几的 用循环查看。后来的思路改为   抽象为数字。

             如八行的矩阵,若表示为    12050000,则表示   在第一行第一列放了一个棋子,第二行第二列放了一个棋子,以及 第四行第五列放了一个棋子。0代表此行无子。

             我的第几位,表示第几行,位上的数字表示第几列,因为同列同行尽可能为1子,故同位 只可能有一个数字。  当然如果反过来写也行。

               故   用book数组标记各列有无元素出现,有则此列不可添加元素。

                     用 tag 数组  并用上述的数字方法  来记录各行各列旗子填放情况。

 

  最终代码的DFS 思路:

                         两个形参:当前填数字的行数,当前已经填放的棋子数。

                         DFS前预处理,对各行的#号的出现列数用vector保存。

                         判断是否填完最后一行,是则判断已填棋子数是否达到题目标准,有则添加ans,递归结束                     

                                                                                                                                                              (判断是否到达结束条件)

                         对当前行,循环填放 vector中的各列 的可能。 若此列尚无元素,就填上,即递归                                        

                                                                                                                                                               ( 递归的具体实现 )

 

                       哎,代码还是要多练啊。

 

上DFS代码:

 

#include"cstdio"
#include"vector"
#include"cstring"
using namespace std;
#define loop(x,y,z) for(x=y;x<z;x++)

char pos[10][10];
int book[10];
int n,k,ans,tag[10];
vector<char>v[10];

void dfs(int i,int sum)
{
    int j;
    if(i==n)
    {
        if(sum==k)
        ans++;
        return;
    }
    int len=v[i].size();
    for(j=0;j<len;j++)
    {
        int x=v[i][j];
        if(!book[x])
        {   tag[i]=x;
            book[x]=1;
            dfs(i+1,sum+1);
            book[x]=0;
        }
    }
    dfs(i+1,sum);
}

int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&k))
    {
        if(n==-1&&k==-1)break;
        memset(book,0,sizeof book);
        memset(tag,-1,sizeof tag);
        loop(i,0,n)
            v[i].clear();
        ans=0;
        loop(i,0,n)
            scanf("%s",pos[i]);
        loop(i,0,n)
            loop(j,0,n)
                if(pos[i][j]=='#')
                v[i].push_back(j);
        dfs(0,0);
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值