HDOJ(HDU).1045 Fire Net (DFS)
HDOJ(HDU).1045 Fire Net [从零开始DFS(7)]
从零开始DFS 
HDOJ.1342 Lotto [从零开始DFS(0)] — DFS思想与框架/双重DFS 
HDOJ.1010 Tempter of the Bone  [从零开始DFS(1)] —DFS四向搜索/奇偶剪枝 
HDOJ(HDU).1015 Safecracker [从零开始DFS(2)]  —DFS四向搜索变种 
HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)]  —小结:做DFS题目的关注点 
HDOJ(HDU).1035 Robot Motion [从零开始DFS(4)]—DFS题目练习 
HDOJ(HDU).1241 Oil Deposits(DFS) [从零开始DFS(5)] —DFS八向搜索/双重for循环遍历 
HDOJ(HDU).1258 Sum It Up (DFS) [从零开始DFS(6)] —DFS双重搜索/去重技巧 
HDOJ(HDU).1045 Fire Net [从零开始DFS(7)]—DFS练习/check函数的思想
题意分析
给出n * n 规模的地图,其中.代表空白区域,X代表墙,求出在满足以下规则的情况下,最多能建立多少座炮楼。 
规则: 
1.假定炮楼可以四向发射炮弹,要求2个炮楼不能互相打到。(射程无限制) 
2.墙可以拦截住炮弹。
相比于之前的dfs题目,本道题的限制要求颇为复杂,首先要求不能互相打到,直观的感觉就是2个炮楼不能处在同一水平/竖直线上。其次要求墙可以拦截子弹,也就是说2个炮楼可以在一条水平/竖直线上的要求就是当且仅当他们中间有墙分隔。 
不难从地图中看出,每一个空白的格子均有可能建炮楼(题目中也说了最大个数一定,但位置有可能有多解)。所以可以确定要遍历整张地图,即判断每个格子是否满足建炮楼的条件,会用到HDOJ(HDU).1241 Oil Deposits(DFS) [从零开始DFS(5)] 讨论过的双重for循环遍历整张地图。 
回到dfs的核心:递归。这道题有没有递归边界呢?首先由于是对地图进行for循环遍历,也就不会出现越界的情况,越界不会是递归边界。其次这道题要求找出数量的最大值,于是在dfs中肯定会有更新最大值的部分。什么时候进行递归呢?当然就是满足题目所说的建立炮楼的规则的时候。 推算到此,可见难点是如何实现这样规则的检查。
继续看如何实现。按照规则,水平/竖直不能有其他的炮楼出现,不难想到,用for循环分别对上下左右四个方向检查,如果遇到炮楼,则说明这个位置不符合规则,返回false,或者是超越了地图边界,退出循环,再或者是遇到了墙 退出当前循环。 为什么遇到墙就跳出循环了呢? 也不难想到,就算墙后面是炮楼,也是符合规则的,所以干脆遇到墙就跳出循环。 
整个程序的架构基本就是这样,下面结合代码,讨论一些小问题。
代码总览
/*
    Title:HDOJ.1045
    Author:pengwill
    Date:2017-2-9
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char mp[5][5];
int visit[5][5];
int n,ans;
void init()
{
    ans = 0;
    memset(visit,0,sizeof(visit));
    for(int i = 0 ;i< n;++i)
        for(int j = 0;j <n; ++j){
            if(mp[i][j] == 'X') visit[i][j] = 2;
        }
}
bool check(int x, int y)
{
    if(x<0 || x>=n || y<0 || y>=n) return false;
    else return true;
}
bool recheck(int x, int y)
{
    if(visit[x][y] == 2 ) return false;
    //right
    for(int i = x;check(i,y);++i){
        if(visit[i][y] == 2) break;
        if(visit[i][y] == 1) return false;
    }
    //left
    for(int i = x;check(i,y);--i){
        if(visit[i][y] == 2) break;
        if(visit[i][y] == 1) return false;
    }
    //up
    for(int i = y;check(x,i);++i){
        if(visit[x][i] == 2) break;
        if(visit[x][i] == 1) return false;
    }
    //down
    for(int i = y;check(x,i);--i){
        if(visit[x][i] == 2) break;
        if(visit[x][i] == 1) return false;
    }
    return true;
}
void dfs(int num)
{
    if(num>ans) ans = num;
    for(int i = 0;i<n;++i){
        for(int j = 0;j<n;++j){
            if(recheck(i,j)){
                visit[i][j] = 1;
                dfs(num+1);
                visit[i][j] = 0;
            }
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)&&n){
        for(int i = 0;i<n;++i) scanf("%s",mp[i]);
        init();
        dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}
init函数完成初始化,地图中的墙标记为2(之后建立的炮楼标记为1,没有访问过就是0);然后进入dfs函数,dfs里面先是更新最大值的部分,然后是是双重for循环。当且仅当此点满足recheck时进行递归操作,recheck就是上下左右检查有没有炮楼,当然,如果这点本身就是墙的话,直接return false。 如果满足的话,把这点标记为炮楼(visit[i][j] = 1),继续递归调用dfs,当然不要忘记无后效性(visit[i][j] = 0)。
HDOJ(HDU).1045 Fire Net (DFS)的更多相关文章
- HDU 1045 - Fire Net - [DFS][二分图最大匹配][匈牙利算法模板][最大流求二分图最大匹配]
		
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1045 Time Limit: 2000/1000 MS (Java/Others) Mem ...
 - HDU 1045 Fire Net(DFS)
		
Fire Net Problem Description Suppose that we have a square city with straight streets. A map of a ci ...
 - HDOJ(HDU).1241 Oil Deposits(DFS)
		
HDOJ(HDU).1241 Oil Deposits(DFS) [从零开始DFS(5)] 点我挑战题目 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架 ...
 - HDOJ(HDU).1035 Robot Motion (DFS)
		
HDOJ(HDU).1035 Robot Motion [从零开始DFS(4)] 点我挑战题目 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架/双重DF ...
 - HDOJ(HDU).2660 Accepted Necklace (DFS)
		
HDOJ(HDU).2660 Accepted Necklace (DFS) 点我挑战题目 题意分析 给出一些石头,这些石头都有自身的价值和重量.现在要求从这些石头中选K个石头,求出重量不超过W的这些 ...
 - HDU 1045 Fire Net(dfs,跟8皇后问题很相似)
		
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others) ...
 - hdu  1045 Fire Net(最小覆盖点+构图(缩点))
		
http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit:1000MS Memory Limit:32768KB ...
 - HDU 1045(Fire Net)题解
		
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定大小的棋盘中部分格子存在可以阻止互相攻击的墙,问棋盘中可以放置最多多少个可以横纵攻击炮塔. [题目分析] 这题本来在搜索专题 ...
 - HDU 1045——Fire Net——————【最大匹配、构图、邻接矩阵做法】
		
Fire Net Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Sta ...
 
随机推荐
- 「日常训练」 Counting Cliques(HDU-5952)
			
题意与分析 题源:2016ACM/ICPC沈阳现场赛. 这题让我知道了什么是团,不过最恶心的还是这题的数据了,卡了无数次- - 解决方法是维护一个G数组,不能去遍历邻接矩阵.至少我改了这么一个地方就过 ...
 - NGUI组件整理总结
			
一图流: 注意: private void RClickUI(Vector3 newPos) { this.gameObject.SetActive(true); this.transform.loc ...
 - 创建一个socket服务实时统计在线人数
			
主要是两个文件,一个是后端文件,一个是前端文件: 后端文件:有人登录了,就通知所有的正在访问的页面,把总人数+1:反之-1: 前端文件:有人登录了,通知后端,页面关闭了,通知后端,同时接收后端派发来的 ...
 - 56[LeetCode] .Merge Intervals
			
Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums s ...
 - 浅谈CPU、内存、硬盘之间的关系
			
计算机,大家都知道的,就是我们日常用的电脑,不管台式的还是笔记本都是计算机.那么这个看着很复杂的机器由哪些组成的呢,今天就简单的来了解一下. 先放图: 图上展示的就是计算机的基本组成啦. 首先是输入设 ...
 - Linux 静态和动态添加路由
			
(一)静态添加 1/5 首先让我们查看当前机器的路由表,执行如下命令:route -n [root@vnode33 network-scripts]# route -n Kernel IP routi ...
 - Repair the Wall (贪心)
			
Long time ago , Kitty lived in a small village. The air was fresh and the scenery was very beautiful ...
 - C++读取文件统计单词个数及频率
			
1.Github链接 GitHub链接地址https://github.com/Zzwenm/PersonProject-C2 2.PSP表格 PSP2.1 Personal Software Pro ...
 - 3dContactPointAnnotationTool开发日志(五)
			
今天要做的第一件事就是把obj文件里不同的对象分割开来. 通过仔细观察发现obj文件中以"o "开头的行会跟着一个对象的名字.g代表对象所属组名,我这里只要用到对象名就行了 ...
 - Vue于React特性简单对比(一)
			
一,对象实体对比 vue的对象实体依然是html,而react的对象实体已经变味jsx,一种新的语法结构. vue的html与react的jsx都可以进行拆分,拆分成更细小的组件,组件之间可以传值. ...