以前用递归的回溯搜索思路做过一次,参见ZOJ1002 Fire Net(递归版),今天想着用非递归的方法试试看,呵呵,比我想象中要难啊,主要还是堆栈里究竟放什么,这一点上思路一直没理清。因此用了整整一天的时间,总算用非递归的方法把1002给AC掉了,在代码中我引入了堆栈层次的概念,模拟系统堆栈的行为,并且在搜索时加入了剪枝,但代码写得还是很烂,继续思考如何改进。

/********************************
Written by : phinecos(洞庭散人)
Data       : 2/11/2008 16:30
Description: 非递归,模拟系统堆栈解决类似八皇后问题
State : Accepted
Run Time: 0ms
Run Memory:    184KB
****************************************/

#include<iostream>
#include <stack>
using namespace std;

const int MAXSIZE = 4;// 地图最大大小
char map[MAXSIZE][MAXSIZE];// 地图
int maxNum,n;

struct Node
{
    int row;//行
    int col;//列
    int level;//当前层次
};

bool CanPut(int row, int col)
{//测试是否可以放置碉堡到row行col列处,因为位置是从小到大前进的,因此只需要测试比待测试点小的位置
    int i;
    //测试col列上是否有面对面的碉堡
    for (i = row - 1; i >= 0; --i)
    {
        if (map[i][col] == 'O') return false;
        if (map[i][col] == 'X') break;
    }
    //测试row行上是否有面对面的碉堡
    for (i = col - 1; i >= 0; --i)
    {
        if (map[row][i] == 'O') return false;
        if (map[row][i] == 'X') break;
    }
    return true;
}

void Solve(int k,int curNum)
{
    stack<Node> s1;//解决树堆栈
    Node node;
    int row,col,i;
    int curLevel = 0;//当前层次

//起始结点入栈
    node.row=k/n;
    node.col = k%n;
    node.level = curLevel;//当前堆栈层次是第0层
    s1.push(node);

while (!s1.empty())
    {
        node = s1.top();
        row = node.row;
        col = node.col;
            
        if (map[row][col]=='.'&&CanPut(row,col)==true)
        {//map[row][col]空闲并且经测试可以放置,则占据此位置
            map[row][col] = 'O';
            //堆栈层次加1
            curLevel++;
            node.level = curLevel;//作为这个堆栈层此的排头兵
            s1.pop();
            s1.push(node);
            curNum++;//放置的棋子数目加1
        }

if (row==n-1&&col==n-1)
        {//来到这个堆栈层的最后一个结点了
            if (curNum>maxNum)
            {//保存这一层的最大数目
                maxNum = curNum;
            }
            if (curLevel==0)
            {//若回到第0层,则说明已经考虑完所有情况了
                break;
            }

/*
            *下面这段代码非常低级趣味,我居然用了两重while循环,It's rubbish,不喜勿进!!!!
            */

//去掉当前堆栈层
            while (!s1.empty())
            {
                node = s1.top();
                if (node.level==curLevel)
                {
                    s1.pop();
                    --k;
                }
                else
                {
                    curLevel--;
                    curNum--;
                    break;
                }
            }
            //有一种情况是栈此时是空的,但还是需要将层次数和棋子数减1,因为循环中它给跳过去了。。。汗。
            if(s1.empty())
            {
                curLevel--;
                curNum--;
            }
            //将上一层的排头兵恢复回来(就是把'O'再此变回'.',并且层次改为这一层)
            ++k;
            row = k/n;
            col = k%n;
            map[row][col] = '.';
            node.row = row;
            node.col = col;
            node.level = curLevel;
            s1.push(node);
            //以上一层排头兵的下一个结点为起点,继续
            if (k+1<n*n)
            {
                ++k;
                node.row = k/n;
                node.col = k%n;
                node.level = curLevel;
                s1.push(node);
            }
            else
            {//当来到最后一个元素时,又有一个特殊的情形,此时当前层次所有情况都已经考虑完毕,因此需要将当前堆栈层给清空掉,哎,这个清空动作和前面是一样的,可居然又单独列了遍代码,吐了。。。
                if (curLevel==0)
                {
                    break;
                }
                while (!s1.empty())
                {
                    node = s1.top();
                    if (node.level==curLevel)
                    {
                        s1.pop();
                        --k;
                    }
                    else
                    {
                        curLevel--;
                        curNum--;
                        break;
                    }
                }

if (s1.empty())
                {
                    curLevel--;
                    curNum--;
                }
                ++k;
                row = k/n;
                col = k%n;
                map[row][col] = '.';
                node.row = row;
                node.col = col;
                node.level = curLevel;
                s1.push(node);

++k;
                node.row = k/n;
                node.col = k%n;
                node.level = curLevel;
                s1.push(node);
            }
            
        }
        else
        {//还没来到这一堆栈层次的最后一个节点,继续吧
            ++k;
            node.row = k/n;
            node.col = k%n;
            node.level = curLevel;
            s1.push(node);
        }
    }
}

int main()
{
    int i,j;
    while(cin>>n&&n!=0)
    {
        //输入地图
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                cin>>map[i][j];
            }
        }
        maxNum=0;//最多可能放置的数目
        //开始深搜,起点设置为左上角
        Solve(0,0);
        cout<<maxNum<<endl;
    }
    return 0;
}

ZOJ1002 Fire Net(非递归版)相关推荐

  1. 图解二叉树非递归版的中序遍历算法

    你会学到什么 讨论的问题是什么 这个问题相关的概念和理论 非递归版中序遍历算法 代码思考 算法技巧 实现代码 快照 评价算法 总结 欢迎关注算法思考与应用公众号 你会学到什么? 树的递归遍历算法很容易 ...

  2. 八皇后问题(非递归版)

    复制代码#include <iostream> #include <stack> using namespace std; const int MAXSIZE = 8;//棋盘 ...

  3. 图解二叉树非递归版的前序遍历算法

    " 图解用栈数据结构对树的前序遍历,中序遍历,后续遍历." 树的遍历 所谓遍历 (Traversal) 是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问.访问结点所做 ...

  4. hdu 4850 字符串构造---欧拉回路构造序列 递归+非递归实现

    http://acm.hdu.edu.cn/showproblem.php? pid=4850 题意:构造长度为n的字符序列.使得>=4的子串仅仅出现一次 事实上最长仅仅能构造出来26^4+4- ...

  5. 2021 - 10 -7 ! 二叉树的前序、中序、后序遍历 非递归思路(迭代版本)

    //! 前序遍历的非递归版本,精髓在于用栈模拟递归的过程,但实际进栈出栈顺序与递归并不一样, //! 比较抽象,建议画图理解,比较重要 void BinarySearchTreesZH::preord ...

  6. 语言非递归求解树的高度_算法素颜(11):无死角“盘”它!二分查找树

    引言 <菜鸟也能"种"好二叉树!>一文中提到了:为了方便查找,需要进行分层分类整理.而满足这种目标的数据结构之一就是树. 树的叶子节点可以看作是最终要搜寻的目标物:叶子 ...

  7. 实现一个二叉树层级遍历_算法总结:左神class5—二叉树递归和非递归实现遍历(后序用一个栈彩蛋)...

    二叉树类型的题目为常考题型 1.能够结合队列.栈.链表.字符串等很多数据结构. 2.需要掌握图的基本遍历方式,比如BFS和DFS. 3.需要掌握递归函数的使用,并自己设计出递归过程. 4.与实际工作结 ...

  8. Binary Tree 非递归遍历模板小结(经典!)

    Binary Tree的遍历可分为preorder, inorder, postorder和in-level order四种.前3种可用递归或非递归(基于stack,后进先出),第4种通常用BFS,基 ...

  9. n皇后问题 递归和非递归

    问题引入 八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇 ...

最新文章

  1. c# lock (obj) 与 lock (this) 区别
  2. [LeetCode]--63. Unique Paths II
  3. python文件打开的合法方式-用python与文件进行交互的方法
  4. 如何看待小米10的葫芦屏?
  5. 应用程序框架实战二十六:查询对象
  6. 多线程中抛异常的这个面试题你会吗?
  7. html图片下方会有一像素,div里嵌套了img底部会有白块问题和图片一像素问题解决 - Macchiato...
  8. hdu 1241Oil Deposits(dfs模板)
  9. Spinnaker:云原生多云环境持续部署的未来
  10. 编辑请求内容 Charles
  11. VB连接ACCESS数据库精简版
  12. 万圣节html代码大全,《方舟 生存进化》万圣节代码大全一览
  13. 360 os3.0 android7.1,【360 N6 Pro】360OS安卓7.1系统V3.0.087付费纯净版ROOT刷机包
  14. 卷积神经网络原理简述
  15. 确定有限自动机DFA和非确定有限自动机NFA
  16. All the python knowledge that I come across
  17. bae java mysql_在百度bae云平台中使用JAVA连接MySQL数据库
  18. Android_GestureDetector手势滑动使用
  19. [1191]电脑耳机孔插上耳机没反应
  20. nav 计算机网络_Wi-Fi 6(802.11ax)解析9:双重NAV技术(Dueling NAVs)

热门文章

  1. bug诞生记——不定长参数隐藏的类型问题
  2. GCC中通过--wrap选项使用包装函数
  3. C++/C++11中头文件numeric的使用
  4. 图片像素、英寸、厘米之间的单位换算
  5. 【C++】google glog详解
  6. java instanceof 报错_java instanceof方法
  7. python 区域和检索_304. 二维区域和检索(Python)
  8. python cv2 轮廓的包络 面积_Python 基于FIR实现Hilbert滤波器求信号包络详解
  9. Fastlane- app自动编译、打包多个版本、上传到app store
  10. vue调试工具如何使用_教你使用Vue.js的DevTools来调试vue项目