poj1623 象限四分树

Squadtrees
Time Limit: 10000MS Memory Limit: 32768K
Total Submissions: 389 Accepted: 143

Description

Quadtrees are data structures used to store digital images. For our purposes, the images will be simple bitmaps, where every pixel is either a 1 (black) or a 0 (white). A quadtree representation of a bitmap is obtained as follows: first, associate the root node with the entire image. If the entire image is either all 1's or all 0's, then store that value in the node and you're done. Otherwise divide the region into four equal size quadrants, add four children to the root, and assign each child one of the four regions in the following order: the first child gets the upper left quadrant, the second the upper right, the third the lower left and the fourth the lower right. Then recursively apply the above rules to each of the children.  
For example, the 4x4 image on the left would be represented by the quadtree on the right:  

Note that this procedure only works as stated if the image is a square and has a side length equal to a power of 2. For those images which do not meet those requirements, we pad the rows and columns with 0's (on the right and on the bottom, respectively) until we have a bitmap of the appropriate size.For example, a 5x13 image would be converted to a 16x16 bitmap (with the original image residing in the upper left portion, and the remainder of the image filled with 0's).  
While quadtrees can result in a significant savings in space over the original image, even more savings can be achieved if we identify repeated subtrees. For example, in the tree above, the first and third subtrees of the root are identical, so we could replace the root of the third subtree with a reference to the first subtree, obtaining something that symbolically looks like the following:  

We will call these compressed quadtrees super quadtrees, or squadtrees. For our purposes the use of a reference saves space only when the tree it replaces has height of at least 1. Thus, while we could replace 5 of the nodes which contain a B with references to the first node with a B, this would not in practice save any space in the compression. Using this rule, our squadtree contains only 12 nodes, as opposed to 17 in the original quadtree. Your job for this problem is to take a set of images and determine the number of nodes in both the resulting quadtrees and squadtrees.

Input

Input will consist of multiple problem instances. Each instance will start with a single line containing two integers n and m, indicating the number of rows and columns in the image. The maximum values for these integers is 128. The next n lines will each contain m characters representing the image to process. A black pixel will be represented by a '1', and a white pixel will be represented by a '0'. The input line 0 0 will terminate input and should not be processed.

Output

For each problem instance, output two integers separated by a single space. The first value is the number of nodes in the quadtree for the problem instance, and the second is the number of nodes in the squadtree.

Sample Input

4 4
1011
0111
1010
0111
6 7
1110111
1010101
0000000
0100010
1011101
1010101
0 0

Sample Output

17 12
61 24


递归写法简单有高效,轻松摘得POJ第一。。。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

struct state{
    int s1,s2,s3,s4;
    state(){}
    state(int n1,int n2,int n3,int n4){
        s1=n1,s2=n2,s3=n3,s4=n4;
    }
    bool check(int n1,int n2,int n3,int n4){
        return s1==n1&&s2==n2&&s3==n3&&s4==n4;
    }
}p[10010];
int tot;
char s[130][130];
int a[130][130];
int vis[20];
int c1,c2;
int div(int x1,int y1,int x2,int y2){
    int tmp=c1;
    c1++,c2++;
    if(x1==x2&&y1==y2) return a[x1][y1];
    int x3=x1+x2>>1,y3=y1+y2>>1;
    int d1=div(x1,y1,x3,y3);
    int d2=div(x1,y3+1,x3,y2);
    int d3=div(x3+1,y1,x2,y3);
    int d4=div(x3+1,y3+1,x2,y2);
    if(d1==0&&d2==0&&d3==0&&d4==0) {c1-=4,c2-=4;return 0;}
    if(d1==1&&d2==1&&d3==1&&d4==1) {c1-=4,c2-=4;return 1;}
    for(int i=2;i<tot;i++)
        if(p[i].check(d1,d2,d3,d4)){
            c1=tmp;
            return i;
        }
    p[tot++]=state(d1,d2,d3,d4);
    return tot-1;
}
int main()
{
    int n,m;
    while(cin>>n>>m,n){
        memset(a,0,sizeof a);
        for(int i=0;i<n;i++){
            scanf("%s",s[i]);
            for(int j=0;s[i][j];j++)
                a[i][j]=s[i][j]-'0';
        }
        int k=1;
        if(n<m) swap(n,m);
        while(k<n) k<<=1;
        memset(vis,0,sizeof vis);
        tot=2,c1=c2=0;
        div(0,0,k-1,k-1);
        printf("%d %d\n",c2,c1);
    }
    return 0;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值