zoukankan      html  css  js  c++  java
  • 2016 长春东北赛---Coconuts(离散化+DFS)

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=5925

    Problem Description
    TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams about eating. One day, TanBig dreams of a field of coconuts, and the field looks like a large chessboard which has R rows and C columns. In every cell of the field, there is one coconut. Unfortunately, some of the coconuts have gone bad. For sake of his health, TanBig will eat the coconuts following the rule that he can only eat good coconuts and can only eat a connected component of good coconuts one time(you can consider the bad coconuts as barriers, and the good coconuts are 4-connected, which means one coconut in cell (x, y) is connected to (x - 1, y), (x + 1, y), (x, y + 1), (x, y - 1).

    Now TanBig wants to know how many times he needs to eat all the good coconuts in the field, and how many coconuts he would eat each time(the area of each 4-connected component).
     
    Input
    The first line contains apositiveinteger T(T10) which denotes the test cases. T test cases begin from the second line. In every test case, the first line contains two integers R and C, 0<R,C109 the second line contains an integer n, the number of bad coconuts, 0n200 from the third line, there comes n lines, each line contains two integers, xi and yi, which means in cell(xi,yi), there is a bad coconut.

    It is guaranteed that in the input data, the first row and the last row will not have bad coconuts at the same time, the first column and the last column will not have bad coconuts at the same time.
     
    Output
    For each test case, output "Case #x:" in the first line, where x denotes the number of test case, one integer k in the second line, denoting the number of times TanBig needs, in the third line, k integers denoting the number of coconuts he would eat each time, you should output them in increasing order.
     
    Sample Input
    2
    3 3 2
    1 2
    2 1
    3 3 1
    2 2
     
    Sample Output
    Case #1:
    2
    1 6
    Case #2:
    1
    8
     
    Source
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  5932 5931 5930 5929 5928 
     
    题意:有一个R*C的棋盘方格,上面有n个障碍点,求这些障碍点将棋盘分割后的每一个区域的方格数,要求先输出分成的区域数,然后从小到大输出方格数;
     
    思路:要求求出每一个区域的方格数,那么可以DFS深搜求出来,但是R*C太大,会超时,所以必须要进行离散化,减小棋盘; 可以分别用两个数组x[] y[] 存储障碍点的横纵坐标,然后从小到大排序,分别对x  y进行离散,这两个离散过程相同,例如在对x进行离散的过程的中如果x[i]==x[i-1]  那么离散到和x[i-1]同一行 ,如果x[i]==x[i-1]+1 那么离散到x[i-1]对应行的下一行, 其余情况离散到x[i-1]对应行的下一行的下一行;
     
    代码如下:
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int N=405;
    LL dx[N],dy[N];///表示每一格压缩的长度;
    bool v[N][N];
    int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    LL r,c;
    int n;
    
    struct Node{
       long long v,p;
       int id;
    }x[N],y[N];
    
    bool cmp1(const Node s1,const Node s2){
       return s1.v<s2.v;
    }
    bool cmp2(const Node s1,const Node s2){
       return s1.id<s2.id;
    }
    
    LL dfs(int sx,int sy)
    {
        LL sum=dx[sx]*dy[sy];
        v[sx][sy]=true;
        for(int i=0;i<4;i++){
            int nx=sx+dir[i][0];
            int ny=sy+dir[i][1];
            if(nx>0&&ny>0&&nx<=r&&ny<=c)
            if(!v[nx][ny]){
                sum+=dfs(nx,ny);
            }
        }
        return sum;
    }
    
    int main()
    {
        int T,Case=1;
        cin>>T;
        while(T--)
        {
           printf("Case #%d:
    ",Case++);
           scanf("%lld%lld%d",&r,&c,&n);
           for(int i=1;i<=n;i++)
           {
               scanf("%lld%lld",&x[i].v,&y[i].v);
               x[i].id=i;
               y[i].id=i;
           }
           sort(x+1,x+n+1,cmp1);
           sort(y+1,y+n+1,cmp1);
           x[n+1].v=r; y[n+1].v=c;
           x[n+1].id=y[n+1].id=n+1;
           x[0].v=y[0].v=1;
           x[0].id=y[0].id=0;
    
           int tot=1;
           dx[1]=1;
           for(int i=1;i<=n+1;i++)
           {
               if(x[i].v==x[i-1].v){
                  x[i].p=tot;
               }
               else if(x[i].v==x[i-1].v+1){
                  x[i].p=++tot;
                  dx[tot]=1;
               }
               else {
                  x[i].p=tot+2;
                  dx[tot+2]=1;
                  dx[tot+1]=x[i].v-x[i-1].v-1;
                  tot+=2;
               }
           }
           r=tot;
           tot=1;
           dy[1]=1;
           for(int i=1;i<=n+1;i++)
           {
               if(y[i].v==y[i-1].v){
                  y[i].p=tot;
               }
               else if(y[i].v==y[i-1].v+1){
                  y[i].p=++tot;
                  dy[tot]=1;
               }
               else {
                  y[i].p=tot+2;
                  dy[tot+2]=1;
                  dy[tot+1]=y[i].v-y[i-1].v-1;
                  tot+=2;
               }
           }
           c=tot;
    
           memset(v,0,sizeof(v));
           sort(x+1,x+n+1,cmp2);
           sort(y+1,y+n+1,cmp2);
           for(int i=1;i<=n;i++)
              v[x[i].p][y[i].p]=true;
           long long ans[N];
           tot=0;
           for(LL i=1;i<=r;i++)
            for(LL j=1;j<=c;j++)
               if(!v[i][j])
               ans[tot]=dfs(i,j),tot++;
            sort(ans,ans+tot);
            printf("%d
    ",tot);
            for(int i=0;i<tot;i++)
                printf("%lld%c",ans[i],(i+1==tot)?'
    ':' ');
        }
        return 0;
    }
  • 相关阅读:
    .NET Core微服务之路:基于Consul最少集群实现服务的注册与发现(二)
    .NET Core微服务之路:基于Consul最少集群实现服务的注册与发现(一)
    在.NET Core中三种实现“可插拔”AOP编程方式(附源码)
    Spreadsheet引用异常解决
    c#字符串中英文混合,根据字符长度截取的函数
    Golang学习-第二篇 搭建一个简单的Go Web服务器
    Golang学习-第一篇 Golang的简单介绍及Windows环境下安装、部署
    受限玻尔兹曼机与MCMC-Gibbs采样计算
    Generative PointNet: Deep Energy-Based Learning on Unordered Point Sets for 3D Generation, Reconstruction and Classification
    【SpringBoot与分布式 04】
  • 原文地址:https://www.cnblogs.com/chen9510/p/5936513.html
Copyright © 2011-2022 走看看