HDU - 1045 Fire Net (dfs 或 二分图)

题意:给出一个不会超过4x4的map
map中有墙,以及空白处。然后你要在空白处放置尽可能多的炮台
炮台对向四周发射子弹,即(炮台不能放在同一行或者列除非有强阻挡)
思路:首先想到了dfs枚举(就像八皇后一样回溯法),我们尽可能多的在
一行一行的放置.关于放置搜索的问题,我们判断是否合法
关于二分图匹配(完全没有想出来怎么匹配..)在网上看了别人的题解才懂
由于同行或者同列不能多个放置(即每行每列只能放一个除了有墙挡)
然后就是建图:将每行每列连续的部分缩成一个点
如图:(画的真的丑...)

我们然后这就有连接关系。假设i为行号,j为列号。ij有一条边,即是图中放了一个(i,j)点
比如在第一行我们可以选择 (1,3)或(1,4)或(1,5)
最大匹配正好是满足连接关系的最大数目,所以用匈牙利算法即可求

二分图代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
char G[5][5];
int map[20][20],col[5][5],row[5][5];
int match[20],vis[20];
int cntx ,cnty,n;
bool Find(int u){
    for(int i=0; i<cnty; i++){
        int x = i;
        if(!vis[x] && map[u][x]){
            vis[x] = 1;
            if(!match[x] || Find(match[x])){
                match[x] = u;
                return true;
            }
        }
    }
    return false;
}
void init(){
    memset(G,0,sizeof(G));
    memset(col,0,sizeof(col));
    memset(row,0,sizeof(row));
    memset(map,0,sizeof(map));
}
int main(){
    while(cin>>n&&n){
        init();
        //从(0,0)开始存图
        for(int i =0;i<n;i++){
            scanf("%s",&G[i]);
        }
        //建图
        cntx= cnty = 1;
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                if(G[i][j] == ‘.‘) row[i][j] = cntx;
                else cntx++;
                if(G[j][i]==‘.‘) col[j][i] = cnty;
                else cnty++;
            }
            cntx++;
            cnty++;
        }

        //连接
        for(int i =0 ;i<n;i++){
            for(int j =0;j<n;j++){
                if(G[i][j]==‘.‘) map[row[i][j]][col[i][j]] = 1;
            }
        }
        int ans = 0;
        memset(match,0,sizeof(match));
        for(int i=0;i<cntx;i++){
            memset(vis,0,sizeof(vis));
            if(Find(i)) ans++;
        }
        cout<<ans<<endl;
    }
}

dfs代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char G[5][5];//记录地图
int hav[5][5];//记录炮台是否存在
int n;
int ans;
bool check(int x,int y) {
    //由于是增行的,所以往前面寻找是否有墙或者炮台
    for(int i = x; i>=1; i--) {
        if(G[i][y] == ‘X‘) break;
        if(hav[i][y] == 1) return 0;
    }
    //往改行之前的列搜索
    for(int i = y; i>=1; i--) {
        if(G[x][i] == ‘X‘) break;
        if(hav[x][i] == 1) return 0;
    }
    return 1;
}
void dfs(int x,int y,int cur) {
    //放置边界
    if(x == n && y == n){
        if(G[x][y] == ‘.‘ &&check(x,y)) cur++;
        ans = max(ans,cur);
        return ;
    }
    //到每行尾,搜索下一行
    if(y == n) {
        if(G[x][y] == ‘.‘ && check(x,y)) {
            hav[x][y]=1;
            dfs(x+1,1,cur+1);
            //回溯
            hav[x][y]=0;
        }
        dfs(x+1,1,cur);
    }
    else {
        if(G[x][y] == ‘.‘ && check(x,y)) {
            hav[x][y]=1;
            dfs(x,y+1,cur+1);
            hav[x][y]=0;
        }
        dfs(x,y+1,cur);
    }

}
int main(){
    while(cin>>n&&n){
        ans = 0;
        memset(hav,0,sizeof(hav));
        for(int i= 1;i<=n;i++){
            scanf("%s",G[i]+1);
        }
        dfs(1,1,0);
        cout<<ans<<endl;
    }
}

原文地址:https://www.cnblogs.com/Tianwell/p/11329569.html

时间: 2024-10-04 16:15:38

HDU - 1045 Fire Net (dfs 或 二分图)的相关文章

HDU 1045 Fire Net(DFS)

Fire Net Problem Description Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall. A blockhouse is a small castle that has four openings t

hdu 1045 Fire Net DFS入门题

Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7012    Accepted Submission(s): 3975 Problem Description Suppose that we have a square city with straight streets. A map of a city is a

HDU 1045 - Fire Net (最大独立集)

题意:给你一个正方形棋盘.每个棋子可以直线攻击,除非隔着石头.现在要求所有棋子都不互相攻击,问最多可以放多少个棋子. 这个题可以用搜索来做.每个棋子考虑放与不放两种情况,然后再判断是否能互相攻击来剪枝.最后取可以放置的最大值. 这里我转化成求最大独立集来做. 首先将每个空地编号,对于每个空地,与该位置可以攻击到的空地连边.找最多的空地使得不互相攻击,即求该图的最大独立集.与搜索做法基本一致,但是说法略有不同. 1 #include<iostream> 2 #include<cstring

HDU 1045 Fire Net 贪心

Problem Description Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a street or a piece of wall. A blockhouse is a small castle that has four openings through wh

HDU 1045 Fire Net(dfs,跟8皇后问题很相似)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 14670    Accepted Submission(s): 8861 Problem Description Suppose that we have a squar

HDU 1045——Fire Net——————【最大匹配、构图、邻接矩阵做法】

Fire Net Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1045 Description Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, e

hdu 1045 Fire Net(最小覆盖点+构图(缩点))

http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1045 Description Suppose that we have a square city with straight streets. A map of a city

HDU 1045 Fire Net 状压暴力

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8073    Accepted Submission(s): 4626 Problem Description Suppose that we have a squar

HDU 1045 Fire Net 二分图Bipartite题解

本题可以使用DFS直接爆搜出答案,不过这样类型的题目其实是个二分图的题解. 这个二分图,难不在Hungary算法,而是难在于建图.需要挺高的抽象思维的. 建图: 1 把同一行不被X分开的格子标同一个号码,被X分开的标下一个号码,这样做是为了缩点,不需要把所有的格子都分开标号,而且可以更方便建个更加小的图. 2 同理把同一列的格子标号 3 然后判断相同一个格子的行标号和列标号是有路径的,其他不在同一个格子的都是没有路径的. 4 这样就等于以行标号和列标号作为左右顶点,构建成一个二分图了 然后使用H