hdu1045 Fire Net (DFS+回溯)

// http://acm.hdu.edu.cn/showproblem.php?pid=1045
#include <string>
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <map>
#include <algorithm>

using namespace std;

vector<vector<int>> grid(6, vector<int>(6, -1)); // 记录图,-1:墙,1:炮,0:道路

int cnt;// 结果,最多可以有多少个炮点
int n; // 图的维度
string s; // 输入的每一行
int road_len; // 可以放置炮点的路径长度
struct node {
    int x; // 横坐标
    int y; // 纵坐标
};
vector<int> dx = {1, -1, 0, 0};// x方向
vector<int> dy = {0, 0, 1, -1}; // y 方向
vector<node> road; //记录dfs 的经过的节点

bool valid(int x, int y) { // 判断边界
    return x >= 0 && x < n && y >= 0 && y < n;
}


bool check(int cur) { // 判断当前的节点上下左右方向是否有炮点,没有,返回true; 有,返回false
    int x, y;
    bool flag = true;

    for (int i = 0; i < 4; i++) {
        x = road[cur].x + dx[i];
        y = road[cur].y + dy[i];

        while (valid(x, y)) {
            int t = grid[x][y];
            if (t == -1) { // 是墙
                break;
            }
            if (t == 1) { // 是炮点
                flag = false;
                return flag;
            }
            x = x + dx[i];
            y = y + dy[i];// 继续沿同一个方向伸展
        }
    }
    return flag;
}

void dfs(int cur, int turn) {
    if (turn > cnt) { // turn 表示前的炮点
        cnt = turn;
    }
    if (cur == road_len) {
        return;
    }

    dfs(cur + 1, turn);// dfs 到road末尾的节点

    if (check(cur)) {
        grid[road[cur].x][road[cur].y] = 1; // 放置炮点
        dfs(cur + 1, turn + 1); // 继续dfs
        grid[road[cur].x][road[cur].y] = 0; // 回溯

    }
}

int main() {


    while (cin >> n && n != 0) {
        road_len = 0;
        cnt = 0;
        road.clear();
        for (int j = 0; j < n; j++) {
            cin >> s;
            for (int i = 0; i < n; i++) {
                if (s[i] == '.') {
                    grid[j][i] = 0;
                    node temp;
                    temp.x = j;
                    temp.y = i;
                    road.push_back(temp); // 记录道路的节点
                    road_len++;
                } else {
                    grid[j][i] = -1;
                }
            }

//            for (int i = 0; i < road_len; i++) {
//                cout << road[i].x << " " << road[i].y << endl;
//            }
        }

        dfs(0, 0);
        cout << cnt << endl;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值