Uva806 Spatial Structures 【递归建树】【习题6-8】

题目:Spatial Structures

题意:黑白图像有两种表示法:点阵表示和路径表示。 路径表示法首先需要把图像转化为四分树,然后记录所有黑结点到根的路径。 将俩种表示法之间进行交换。结点是由路径构成的五进制再转换成十进制的值。NWNESWSE分别用1234表示。

思路:因为是四分树,一个矩阵横纵平分即为四分,所以不断的平分矩阵建树。

1.点阵转换路径:

dfs1(int r,int c,int w,double res,int floor){//将图转化为结点:r:左上角横坐标,c:左上角纵坐标,w:矩阵大小,res:计算结点的值,floor:层数
不断的递归寻找,每次递归顺便在递归式中直接将五进制计算为十进制;直到寻找到当前的矩阵全部为1即为结点,将其保存。

每次平分矩阵时有四个,将平分的矩阵的左上角的横纵坐标传入。

最后将结点排序,按每行最多12个输出即可。

2.路径转换点阵:

dfs2(int r,int c,int w,int floor){//将结点转化为图:r:矩阵左上角横坐标,c:矩阵左上角纵坐标,floor:层数
将每个结点转换成五进制,五进制的值即为路径,根据五进制递归,直到达叶子结点即五进制值的最后一个值,将其所在的矩阵染成*即可。

注意:输入输出格式是:先输入个数,然后换行(第一次不换),然后输出Image ,然后输入案例,最后输出结果。

代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 70;
char marix[maxn][maxn];
vector<double>node;
void dfs1(int r,int c,int w,double res,int floor){//将图转化为结点:r:左上角横坐标,c:左上角纵坐标,w:矩阵大小,res:计算结点的值,floor:层数
    int cot = 0;
    for(int i=r;i<r+w;i++){//计算当前矩阵中的面积即1的个数
        for(int j=c;j<c+w;j++){
            if(marix[i][j] == '1') cot++;
        }
    }
    if(cot == 0) return;//当1的个数为0说明为空结点
    else if(cot == w*w){//当当前矩阵全部为1说明是结点
        node.push_back(res);//将结点保存
    }
    else{
        dfs1(r    ,c    ,w/2,res+1*pow(5,floor),floor+1);//上左
        dfs1(r    ,c+w/2,w/2,res+2*pow(5,floor),floor+1);//上右
        dfs1(r+w/2,c    ,w/2,res+3*pow(5,floor),floor+1);//下左
        dfs1(r+w/2,c+w/2,w/2,res+4*pow(5,floor),floor+1);//下右
    }
}
int len,tran[maxn];
int translate(long long v,int tra[]){//五进制转换
    int i=0;
    while(v){
        tra[i++] = v%5;
        v/=5;
    }
return i;}

void dfs2(int r,int c,int w,int floor){//将结点转化为图:r:矩阵左上角横坐标,c:矩阵左上角纵坐标,floor:层数
    if(floor == len){
        for(int i=r;i<r+w;i++){
            for(int j=c;j<c+w;j++)
                marix[i][j] = '*';
        }
        return;
    }
    if(tran[floor] == 1) dfs2(r    ,c    ,w/2,floor+1);//上左
    if(tran[floor] == 2) dfs2(r    ,c+w/2,w/2,floor+1);//上右
    if(tran[floor] == 3) dfs2(r+w/2,    c,w/2,floor+1);//下左
    if(tran[floor] == 4) dfs2(r+w/2,c+w/2,w/2,floor+1);//下右
}
int main()
{
    int n,kcase=0;
    while(cin >> n && n){
        if(kcase) cout<<endl;//这个是坑!
        cout <<"Image "<<++kcase<<endl;
        if(n > 0){
            for(int i=0;i<n;i++) cin >>marix[i];
            node.clear();
            dfs1(0,0,n,0,0);
            sort(node.begin(),node.end());//将结点排序
            for(int i=0;i<node.size();i++){//将结点输出,每行最多12个 
                cout <<node[i];
                if((i+1)%12 == 0 || i == node.size()-1) cout<<endl;
                else cout<<" ";
            }
            cout << "Total number of black nodes = "<<node.size()<<endl;
        }else{
            int a[10000],index=0;
            while(cin>>a[index] && a[index++] != -1);
            index--;
            memset(marix,'.',sizeof(marix));
            for(int i=0;i<index;i++){
                len = translate(a[i],tran);
                dfs2(0,0,-n,0);
            }
            for(int i=0;i<-n;i++){
                for(int j=0;j<-n;j++) cout << marix[i][j];
                cout<<endl;
            }
        }
    }
return 0;}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值