• 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;
    }
  • 相关阅读:
    javascript中的this和e.target的深入研究
    mysql基础
    php每天一题:怎么在不使用第三个变量的情况下交换两个变量的值
    用原生javascript实现在页面动态显示时间
    php每天一题:strlen()与mb_strlen()的作用分别是什么
    javascript每天一题
    php中用foreach改变数组的值的问题
    程序员进阶之路
    hdu6638 线段树求最大子段和
    P4513 小白逛公园 动态维护最大子段和
  • 原文地址:https://www.cnblogs.com/chen9510/p/5936513.html
Copyright © 2020-2023  润新知