ZOJ 1002 - Fire Net 的答案(回溯法)

       ---------------------------------------------------------------------------------------------------------------------------

       严格来讲,此题并不算我做出来的。因为我在WA后忍不住搜索了这道题的网上资料,并在参考了“洞庭散人”的代码后AC的。  

       ----------------------------------------------------------------------------------------------------------------------------

        ZOJ 1002: Fire Net(碉堡 火力网)

        http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2

        此题大意是在一个最大4*4网格组成的城市里,每个网格可能为“墙壁”(用‘X’表示)和“街道”(用‘.’表示)。现在在街道放置碉堡,每个碉堡可以向上下左右四个方向开火,子弹射程无限远。墙壁可以阻挡子弹。问最多能放置多少个碉堡,使它们彼此不会互相摧毁。

       例如输入:

       .X..
       ....
       XX..
       ....

       则应输出最大个数为5。

       此题和n后问题非常类似,因此可用回溯法搜索整个解空间树。最开始我使用了“贪心法”但是WA,原因就在于贪心法的特点是:得到的解不一定是整体最优解。因此还是得用回溯法搜索整个空间树。和n后问题解法一样,CanPut是判别函数,判断位置(x,y)是否能放置碉堡。

       以下是我写的代码,但大体上都参考了洞庭散人的文章(代码在本质上完全一致):

       http://www.cnblogs.com/phinecos/archive/2008/09/18/1293017.html

 

Code_1002_Fire_Net
/*ZOJ 1002 - Fire Net */
/*n最大为4,使用回溯法搜索解空间树*/
#include <stdio.h>

char map[4][5];
int maxCount;/*最多可放置碉堡数*/

/* 测试(x,y)位置是否可以放置碉堡 */
int CanPut(int n, int x, int y)
{
    /*因为行列是递增的,因此只需向上和向左搜索是否有碉堡即可*/
    int i;

    /*向左推移, 0表示不能被占用*/
    i=x;
    while(i>0 && map[i-1][y]!='X') 
        if (map[--i][y]=='O') return 0;
    

    /*向上*/
    i=y;
    while(i>0 && map[x][i-1]!='X')
        if(map[x][--i]=='O') return 0;
            
    /*可以放置*/
    return 1;
}

/*找出最大碉堡树, n是city的尺寸,k是距离起始点的一维长度距离*/
void Search(int n, int k, int curCount)
{
    int x,y;
    if(k==n*n)
    {
        /*arrived the bottom*/
        if(curCount>maxCount)
            maxCount=curCount;
        return;
    }
    else
    {
        x=k/n;
        y=k%n;
        if(map[x][y]=='.' && CanPut(n,x,y))
        {
            /*该点可以放置,则进入该分支*/
            map[x][y]='O';/*put a houseblock*/
            Search(n, k+1, curCount+1);
            /*回退*/
            map[x][y]='.';
        }
        /*向下一个分支*/
        Search(n,k+1,curCount);
    }
}

int main()
{
    int n,i,count;
    while(scanf("%d",&n)!=EOF && n>0)
    {
        for(i=0;i<n;i++)
            scanf("%s", map[i]);
        
        maxCount=0;
        Search(n, 0, 0);
        printf("%d\n",maxCount);
    }
}

 

时间: 2024-07-28 18:38:28

ZOJ 1002 - Fire Net 的答案(回溯法)的相关文章

算法——回溯法

回溯法 回溯法有"通用的解题法"之称.用它可以系统地搜索一个问题的所有解或任一解.回溯法是一种即带有系统性又带有跳跃性的搜索算法.它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树.算法搜索至解空间树的任一结点时,先判断该节点是否包含问题的解.如果不包含,则跳过对以该节点为根的子树的搜索,逐层向其它祖先节点回溯.否则,进入该子树,继续按照深度优先策略搜索.回溯法求问题的所有解时,要回溯到根,且根节点的所有子树都已被搜索遍才结束.回溯法求问题的一个解时,只要搜索到问题的一个解

回溯法 -数据结构与算法

1.回溯法算法思想:   定义:         回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为"回溯点". 1.回溯法适用:有许多问题,当需要找出它的解集(全部解)或者要求回答什么解是满足某些约束条件的最优解时,往往要使用回溯法. 2.有组织的穷举式搜索:回溯法的基本做法是搜索或者有的组织穷尽搜索.它能避免搜索所有的可能

常用算法:C#用回溯法找出n个自然数中取r个数的全排列

回溯法也称为试探法,该方法首先暂时放弃关于问题规模大小的限制,并将问题的候选解按某种顺序逐一枚举和检验.在回溯法中,放弃当前候选解,寻找下一个候选解的过程称为回溯. 本实例是用回溯法输出n个自然数中以r个数全排列.代码如下: <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />public void Arrange(int n, int r) int i = 0, j; st

PHP回溯法解决0-1背包问题实例分析

 这篇文章主要介绍了PHP回溯法解决0-1背包问题,实例分析了php回溯法解决背包问题的技巧,具有一定参考借鉴价值,需要的朋友可以参考下     本文实例讲述了PHP回溯法解决0-1背包问题的方法.分享给大家供大家参考.具体分析如下: 这段代码是根据<软件设计师>教程的伪代码写的: 最麻烦的不是伪代码改成php,而是数组下标从0开始,及相应的下标判断问题: 带着调试输出一块写上 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

javascript递归回溯法解八皇后问题

  javascript递归回溯法解八皇后问题:           网上看到许多关于八皇后算法的文章,很少能看到使用javascript来实现的,今天就给大家使用javascript来解决下这个问题,有需要的小伙伴可以参考下. 下面给大家分享的是回溯法解八皇后, 带详细注解,这里就不多废话了. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

读书时间--回溯法浅析:逆向思维领略算法之美

下面将使用回溯思想解决若干经典问题并通过它们来说明使用回溯的基本思路 什么叫回溯法 回溯是一种比较简单.比较常用的搜索策略. 它的基本思想是假设某问题的解决步骤可能有N步,且每一步的解决方法又可能有M种,那么就按照某种顺序依次试探每一步中的各种方法,一旦某一步的所有方法都失效,那么就返回上一步继续试探上一步骤的其他M−1种方法.简而言之就是从一条路往前走,能进则进,不能进则退回来,换一条路再试. 通常用回溯法解决问题的一般步骤为:首先,定义一个解空间,它包含问题的解,也就是每一步所采用的各种方法

优化-01背包回溯法计算起来非常慢,有木有算法大大帮忙看看

问题描述 01背包回溯法计算起来非常慢,有木有算法大大帮忙看看 #include #include #include #include #include #include using namespace std; int n;//物品数量 double c;//背包容量 double v[9000];//各个物品的价值 double w[9000];//各个物品的重量 double cw = 0.0;//当前背包重量 double cp = 0.0;//当前背包中物品价值 double best

源代码-求大神,ZOJ 1002题怎么老出错

问题描述 求大神,ZOJ 1002题怎么老出错 题目链接http://acm.zju.edu.cn/onlinejudge/showRuns.do?contestId=1 提交结果老是的回复是 wrong answer. 样本输入输出都正确. 我提交是用C++提交的,这个应该不成问题 求大神指点. C语言 以下是我提交的源代码 #include"stdio.h" #define N 6 char net[N][N];//最大存储数据容量 int MAX,max;//MAX为最终最大值,

回溯法——求解0-1背包问题

         以前研究过一个简单的N皇后问题,对回溯法也有了个模糊的认识,大致理解就是:先一直做某件事,当完成某个条件时或者是触犯某个条件时,再返回到最近的一个类似还原点的地方.        在用回溯法求解0-1背包问题的时候,主要遇到三个相对难解决的问题:1,什么是界限函数:2,什么时候用它:3,回溯到哪儿.    什么是界限函数?         如下图:             当我们身在一棵搜索空间树中,站在一个K点举棋不定的时候,我们可以用它估算如果我们继续向下走,我们走完本段路