石油采集(求联通区域) 2018多校寒假集训 (dfs+二分匹配)

题目:

链接:https://www.nowcoder.com/acm/contest/76/A
来源:牛客网

随着海上运输石油泄漏的问题,一个新的有利可图的行业正在诞生,那就是撇油行业。如今,在墨西哥湾漂浮的大量石油,吸引了许多商人的目光。这些商人们有一种特殊的飞机,可以一瓢略过整个海面20米乘10米这么大的长方形。(上下相邻或者左右相邻的格子,不能斜着来)当然,这要求一瓢撇过去的全部是油,如果一瓢里面有油有水的话,那就毫无意义了,资源完全无法利用。现在,商人想要知道,在这片区域中,他可以最多得到多少瓢油。

地图是一个N×N的网络,每个格子表示10m×10m的正方形区域,每个区域都被标示上了是油还是水

输入描述:

测试输入包含多条测试数据测试数据的第一行给出了测试数据的数目T(T<75)每个测试样例都用数字N(N<50)来表示地图区域的大小,接下来N行,每行都有N个字符,其中符号’.’表示海面、符号’#’表示油面。

输出描述:

输出格式如下“Case X: M”(X从1开始),M是商人可以最多得到的油量。

示例1

输入

1
6
......
.##...
......
.#..#.
.#..##
......

输出

Case 1: 3

题意:中文题不解释

思路:way1:dfs爆搜就OK啊,,,这么简单的题目不知道为什么当时没有出     way2:二分匹配

代码1:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,m;
char mp[106][106];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int ans1,ans2;
void DFS(int i,int j)
{
    int nx,ny;
    if(i<0||i>=m||j<0||j>=n||mp[i][j]==‘.‘)
        return ;
        if((i+j)%2==0)ans1++;
        else ans2++;
    mp[i][j]=‘.‘;
    for(int zz=0;zz<4;zz++)
    {
        nx=i+dx[zz];
        ny=j+dy[zz];
    DFS(nx,ny);
    }
    return ;
}
int main()
{
    int i,j,res=0;
    int t;
    cin>>t;
    for(int o=1;o<=t;o++){
        cin>>m;
        n=m;
        getchar();
        for(i=0;i<m;i++)
        {

            for(j=0;j<n;j++)
        {
            scanf("%c",&mp[i][j]);
        }
                    getchar();
        }
        for(i=0;i<m;i++)
            for(j=0;j<n;j++)
        {

            if(mp[i][j]==‘#‘)
            {
                 ans1=0;
                ans2=0;
                DFS(i,j);
                res+=min(ans1,ans2);
            }
        }
      printf("Case %d: %d\n",o,res);
    }
    return 0;
}

代码2:(思路简单就不自己写了)

#include <iostream>
#include <queue>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <map>
using namespace std;
const int maxn=2000;
int girl[maxn],used[maxn],line[maxn][maxn],path[60][60],temp1,temp2;
char a[60][60];
bool find(int x)
{
    for (int i=1;i<temp2;i++)
    if (line[x][i]&&!used[i]) //x与i有关系
    {
        used[i]=1;
        if (girl[i]==0||find(girl[i])) //名花无主或者还能腾位置;
        {
            girl[i]=x;
            return true;
        }
    }
    return false;
}
int main()
{

    int t,n,ans,tt;
    cin>>t;
    tt=1;
    while (t--)
    {
        ans=0;
        temp1=temp2=1;
        memset(line,0,sizeof(line));
        memset(girl,0,sizeof(girl));
        memset(path,0,sizeof(path));
        cin>>n;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            {
                cin>>a[i][j];
                if ((i+j)%2==0)
                path[i][j]=temp1++;
                else
                path[i][j]=temp2++;
            }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            {
                if ((i+j)%2==1&&a[i][j]==‘#‘)
                {
                    if (path[i-1][j]>=1&&a[i-1][j]==‘#‘)
                    line[path[i-1][j]][path[i][j]]=1;
                    if (path[i+1][j]>=1&&a[i+1][j]==‘#‘)
                    line[path[i+1][j]][path[i][j]]=1;
                    if (path[i][j-1]>=1&&a[i][j-1]==‘#‘)
                    line[path[i][j-1]][path[i][j]]=1;
                    if (path[i][j+1]>=1&&a[i][j+1]==‘#‘)
                    line[path[i][j+1]][path[i][j]]=1;
                }
            }
        for (int i=1;i<temp1;i++)
        {
            memset(used,0,sizeof(used));
            if (find(i))
            ans++;
        }
        cout<<"Case "<<tt++<<": "<<ans<<endl;
    }
}

简单题

原文地址:https://www.cnblogs.com/huangzzz/p/8446352.html

时间: 2024-10-27 08:53:44

石油采集(求联通区域) 2018多校寒假集训 (dfs+二分匹配)的相关文章

牛客网NowCoder 2018年全国多校算法寒假训练营练习比赛(第四场)A.石油采集(dfs) B.道路建设(最小生成树prim) C.求交集(暴力) F.Call to your teacher(迪杰斯特拉乱用) H.老子的全排列呢(dfs)

菜哭了... A.石油采集 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 链接:https://www.nowcoder.com/acm/contest/76/A来源:牛客网 题目描述 随着海上运输石油泄漏的问题,一个新的有利可图的行业正在诞生,那就是撇油行业.如今,在墨西哥湾漂浮的大量石油,吸引了许多商人的目光.这些商人们有一种特殊的飞机,可以一瓢略过整个海面20米乘10米这么大的长方形.(上下相

C. Learning Languages 求联通块的个数

C. Learning Languages 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <stack> 9 #include <queue&

HDU 4738 Caocao&#39;s Bridges ——(找桥,求联通块)

题意:给你一个无向图,给你一个炸弹去炸掉一条边,使得整个图不再联通,你需要派人去安置炸弹,且派去的人至少要比这条边上的人多.问至少要派去多少个,如果没法完成,就输出-1. 分析:如果这个图是已经是多个联通块了,那么一个人都不用去,如果不是,那么只要找出这个无向图上的桥并且哨兵数量最少的那座把它炸了就行(输出这条边上的哨兵数量即可).直接tarjan就可以写. 注意点:1.可能有重边,所以用手写邻接表的方式存图:2.如果一座桥上没有哨兵,那么你也得至少派去一个人去安置炸弹(因为炸弹不会自己飞过去啊

分别利用并查集,DFS和BFS方法求联通块的数量

联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块: 题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m行(输入数据到文件截止): 输出:第一行要求输出联通块的个数,并在第二行分别输出每个联通块中点的数量,每个数之间以一个空格隔开. 样例 15 31 42 53 5输出:2 2 3样列2 9 81 22 33 43 74 54 67 87 9输出: 19 如果不明白的话可以画图试试,最多花半个小时,要是早这样不

PAT甲题题解-1013. Battle Over Cities (25)-求联通分支个数

题目就是求联通分支个数删除一个点,剩下联通分支个数为cnt,那么需要建立cnt-1边才能把这cnt个联通分支个数求出来怎么求联通分支个数呢可以用并查集,但并查集的话复杂度是O(m*logn*k)我这里用的是dfs,dfs的复杂度只要O((m+n)*k)这里k是指因为有k个点要查询,每个都要求一下删除后的联通分支数.题目没给定m的范围,所以如果m很大的话,dfs时间会比较小. for一遍1~n个点,每次从一个未标记的点u开始dfs,标记该dfs中访问过的点.u未标记过,说明之前dfs的时候没访问过

利用DFS求联通块个数

/*572 - Oil Deposits ---DFS求联通块个数:从每个@出发遍历它周围的@.每次访问一个格子就给它一个联通编号,在访问之前,先检查他是否 ---已有编号,从而避免了一个格子重复访问多次 --*/ #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int maxn =

【紫书】Oil Deposits UVA - 572 dfs求联通块

题意:给你一个地图,求联通块的数量. 题解: for(所有还未标记的'@'点) 边dfs边在vis数组标记id,直到不能继续dfs. 输出id及可: ac代码: #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" #include<stdio.h> #include<algorithm> #include<string> #include<vector> #include<list&

任意点~并查集求联通块

链接:https://www.nowcoder.com/acm/contest/84/C来源:牛客网 任意点 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 平面上有若干个点,从每个点出发,你可以往东南西北任意方向走,直到碰到另一个点,然后才可以改变方向. 请问至少需要加多少个点,使得点对之间互相可以到达. 输入描述: 第一行一个整数n表示点数( 1 <= n <= 100).第二行n行,

【2018年全国多校算法寒假训练营练习比赛(第四场)-A】石油采集(匈牙利算法)

试题链接:https://www.nowcoder.com/acm/contest/76/A [思路] 每个‘#’的右边和下边如果也是‘#’说明这两个点构成通路,以此重构一幅图,然后找二分图的最大匹配. [代码] #include<bits/stdc++.h> using namespace std; char mp[55][55]; bool vis[2505]; vector<int>G[2505]; int mp1[55][55], match[2505], n; bool