hdu 6665 Calabash and Landlord (2019 Multi-University Training Contest 8 1009)(离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6665

题目大意:给定四个点分别为两个矩形的左上角和右下角,两个矩形与坐标轴平行,问坐标平面(含负轴,但矩形只在第一象限内,部分边可能在正轴上)被两个矩形划分为几个区域(原意问的是几个连通点集但因为是实数点所以相当于问的是区域)。

思路:如题,离散化。可以看到点坐标的值可能非常大,但是注意求的只是区域个数,而并不用求每个区域内点的个数,所以我们想要的信息只有点和点之间的位置关系,这时候最简单的方法,就是枚举每个点之间的关系,但是这个太累了(没错偷懒才是人类进步的源泉),大致算一下有二十多种,就算有部分情况是重叠的也要全部列先一遍吧,就是很麻烦(确信)。这时候就要用到离散化,如前所言,我们只需要点和点之间的位置关系,那么我们就可以在不改变他们相对随意改变值的大小,也就是说可以把很大的值降到很小的范围内然后。。。然后就可以暴力涂色了。

具体的操作就是,先把所有的x,y值放在一起排序,然后从小到大赋值,我选择的是从零开始赋偶数值,这样避免了某些实数点在涂色时无法涂到导致区域没有被统计的情况(相当于加大了线和线之间的距离),然后重新排序,排成读入的顺序,然后直接给每条边打上标记,然后就可以dfs涂色了。

代码如下:

#include<iostream>
#include<cstdio>
#include<set>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<algorithm>
#include<map>
#include<stack>
using namespace std;
int co[20][20];
struct node
{
    int v;
    int id;
} e[20];
int cc;
bool cmp(node a,node b)
{
    return a.v<b.v;
}
bool cmpid(node a,node b)
{
    return a.id<b.id;
}
int chec(int x,int y)//检查是否越界或已经被涂色
{
    if(x>=20||y>=20||x<0||y<0||co[x][y]!=0)
    {
        return 0;
    }
    return 1;
}
int mi[4][2]= {0,-1,0,1,1,0,-1,0};
int dfs(int x,int y,int cc)
{
    co[x][y]=cc;
    for(int i=0; i<4; i++)
    {
        if(chec(x+mi[i][0],y+mi[i][1]))
        {
            dfs(x+mi[i][0],y+mi[i][1],cc);
        }
    }
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(co,0,sizeof(co));
        for(int i=0; i<8; i++)
        {
            scanf("%d",&e[i].v);
            e[i].id=i;
        }
        sort(e,e+8,cmp);//排序后离散化
        int k=2;
        int be=e[0].v;
        e[0].v=2;
        for(int i=1; i<8; i++)//离散化的赋值阶段
        {
            if(e[i].v==be)
            {
                e[i].v=k;
            }
            else
            {
                be=e[i].v;
                k+=2;
                e[i].v=k;
            }
        }
        sort(e,e+8,cmpid);//排回原序
        for(int i=0; i<8; i+=4)//标记线段
        {
            for(int j=e[i].v; j<=e[i+2].v; j++)
            {
                co[j][e[i+1].v]=-1;
                co[j][e[i+3].v]=-1;
            }
            for(int j=e[i+1].v; j<=e[i+3].v; j++)
            {
                co[e[i].v][j]=-1;
                co[e[i+2].v][j]=-1;
            }
        }
        cc=0;
        for(int i=0; i<20; i++)//涂色
        {
            for(int j=0; j<20; j++)
            {
                if(co[i][j]==0)
                {
                    dfs(i,j,++cc);
                }
                //printf("%2d ",co[i][j]);
            }
        }
        printf("%d\n",cc);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/forever3329/p/11367630.html

时间: 2024-09-29 09:47:02

hdu 6665 Calabash and Landlord (2019 Multi-University Training Contest 8 1009)(离散化)的相关文章

HDU 4906 Our happy ending(2014 Multi-University Training Contest 4)

题意:构造出n个数 这n个数取值范围0-L,这n个数中存在取一些数之和等于k,则这样称为一种方法.给定n,k,L,求方案数. 思路:装压 每位 第1为表示这种方案能不能构成1(1表示能0表示不能)  第2为表示能不能构成2 ...  这样用d[1<<n] 的DP  像背包那样背 n次就可以 最后状态中第k位为1的就可以加上方法数. #include<cstring> #include<cstdio> #include<cmath> #include <

HDU 4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)

题意:给定n*m个格子,每个格子能填0-k 的整数.然后给出每列之和和每行之和,问有没有解,有的话是不是唯一解,是唯一解输出方案. 思路:网络流,一共 n+m+2个点   源点 到行连流量为 所给的 当前行之和.    每行 连到每一列 一条流量为  k的边,每列到汇点连 列和.如果流量等于总和则有解,反之无解(如果列总和不等于行总和也无解).  判断方案是否唯一 找残留网络是否存在长度大于2的环即可,有环说明不唯一. #include<cstdio> #include<cstring&

hdu 5792 World is Exploding(2016 Multi-University Training Contest 5——树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5792 World is Exploding Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 643    Accepted Submission(s): 306 Problem Description Given a sequence A

hdu 5774 Where Amazing Happens(2016 Multi-University Training Contest 4——打表)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5774 Where Amazing Happens Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 443    Accepted Submission(s): 300 Problem Description As the premier m

hdu 6406 Taotao Picks Apples (2018 Multi-University Training Contest 8 1010)(二分,前缀和)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6406 思路: 暴力,预处理三个前缀和:[1,n]桃子会被摘掉,1到当前点的最大值,1到当前点被摘掉的桃子的数量,然后我们枚举修改p点造成的所有影响,: 1,假如新输入的点比原先的点的值更大,那么我们对修改后p这个点的值和[1,p-1]的最大值关系进行分析,也就是分析前半段的影响:(1)如果p点大于1-p-1的最大值的时候我们直接利用前缀和O(1)得到[1,p-1]有多少个桃子被摘掉,然后加上当前这个.(

2019 HDOJ Multi-University Training Contest Stage 2(杭电多校)

服务器时不时爆炸,有点难受. 题目链接:http://acm.hdu.edu.cn/userloginex.php?cid=849 A: 神仙题.不可做题. B: dp. C: 推式子题. D: 边分治. E: 可以数学推理的题.但是显然打表更快找出规律.对打出来的结果做两次差分即可. 1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou doubl

2019 HDOJ Multi-University Training Contest Stage 4(杭电多校)

很抱歉过了这么多天才补这场,最近真的挺忙的…… 出题人是朝鲜的(目测是金策工业?),挺难. 题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=851 A: 签到题. 对于当前的点,若其编号为偶数,则可与1相连使得边权贡献为0.否则从低位向高位找当前点编号的二进制表示的第一个0,使这个0变为1,其他位置变为0并检查新的数字是否小于等于n.若小于等于n则贡献为0,反之贡献为1. 1 /* basic header */ 2 #inclu

2019 HDOJ Multi-University Training Contest Stage 8(杭电多校)

中规中矩的一场. 题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=855 C: 定义函数f(d,k)为数字d在数字k中出现的次数.给定d和x,找到尽量大的k使得k<=x且f(d,k)==k. 很诡异的一题,最好的做法仍然是打表找规律.题解给了一个很神奇的结论:满足条件的k<1011且k的分布非常稀疏. 1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* defin

2019 HDOJ Multi-University Training Contest Stage 10(杭电多校)

最后一场多校打得一般般. 题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=857 C: E: I: BFS水题. 1 /* Codeforces Contest 2019_mutc_10 2 * Problem I 3 * Au: SJoshua 4 */ 5 #include <queue> 6 #include <cstdio> 7 #include <vector> 8 #include <s