GOJ 1211 -- 花开雷霆崖 简单分治算法的应用

题目在这里,半年多以前做过的一道题了,印象比较深刻是因为那是某一天晚上突然在《算法竞赛入门经典》这本书上看到这个问题,刚好想起这道题当时不会做,就一时兴起把代码敲出来,WA了一次后debug了一会后就AC了。

花开雷霆崖

Time Limit:2000MS  Memory Limit:65536K
Total Submit:10 Accepted:3

Description

雷霆崖上的牛头人酋长凯○•血蹄有一块荒芜的太阳花田,但是某一天,它发现花田上奇迹般的开了一朵奇迹之花!于是它兴冲冲的跑去暴风城买花,打算在花田上的其他地方也种满花。 

但是当他买好花以后却犯愁了,因为它家的花田是一 由2^k*2^k 个方格组成 的正方形,而买来的4种花形状又古怪(见下图描述),于是血蹄酋长想请您帮他想一个方法,让他可以把花田种满鲜花。 
 
(4种花的形状分别对应1,2,3,4,种植的时候不能旋转或者翻转,0表示酋长最早发现的奇迹之花的形状)

Input

多组数据测试,直到文件结束(EOF) 
每行一个K,N,M,分别代表花田的大小(长宽均为2的K次方,1<=K<=9),奇迹之花位于N行M列 

Output

0表示奇迹之花的位置,1表示此格上中的是第一种花,2表示此格上中的是第二种花,以此类推。 
每组数据一个输出,然后输出一个换行。 

Sample Input

 

1  0  1
3  7  6

 

Sample Output

 

30
33

11221122
11121222
31112224
33111244
11311122
13331112
33343122
33443302

 

Hint

对于第一组数据,图如下: 
 
对于第二组数据,图如下: 

花田的面积是2^k * 2^k,所以如果把花田切割成4个小正方形,就变成4个2^(k-1) * 2^(k-1)的正方形了,可以知道4个中的其中一个必定会有一个有奇迹之花,再把这个有奇迹之花的正方形切割成4个,这样一直递归下去,最后可以得到一个2*2的带有奇迹之花的正方形。现在的问题是,每次切割的时候,另外三个没有奇迹之花的正方形要怎么处理?方法很简单,就是给他构造一个,三个刚好可以凑成一种花的形状。例如第一次切割的时候可以把中间的那块看成是奇迹之花:

后面的以此类推,最后就能得出正确答案。

思路很清晰,但是中间的步骤还是挺多的,代码量还是挺多的,细节要注意。我的代码有点繁琐,很多if……else

 

View Code
#include<stdio.h>
#include<math.h>
#include<string.h>
int k,n,m,t,side;
int map[1000][1000];
void func(int x,int y,int ax,int ay,int length)
{
    int midx,midy;
    length/=2;
    midx=x+length-1;
    midy=y+length-1;
    if(length==1)
    {
        if(x==ax)
        {
            if(y==ay)
                map[ay][ax+1]=map[ay+1][x]=map[ay+1][ax+1]=4;
            else
                map[ay][ax+1]=map[ay-1][x]=map[ay-1][ax+1]=2;
        }
        else
        {
            if(y==ay)
                map[ay][ax-1]=map[ay+1][ax]=map[ay+1][ax-1]=3;
            else
                map[ay][ax-1]=map[ay-1][ax]=map[ay-1][ax-1]=1;
        }
    }
    else
    {
        if(ax<=midx&&ay<=midy)
        {        
            map[midy][midx+1]=map[midy+1][midx]=map[midy+1][midx+1]=4;
            func(x+length,y,midx+1,midy,length);
            func(x,y+length,midx,midy+1,length);
            func(x+length,y+length,midx+1,midy+1,length);
            func(x,y,ax,ay,length);
        }
        else if(ax<=midx&&ay>midy)
        {
            
            map[midy][midx]=map[midy][midx+1]=map[midy+1][midx+1]=2;
            func(x,y,midx,midy,length);
            func(x+length,y+length,midx+1,midy+1,length);
            func(x+length,y,midx+1,midy,length);
            func(x,y+length,ax,ay,length);
        }
        else if(ax>midx&&ay<=midy)
        {
            
            map[midy][midx]=map[midy+1][midx]=map[midy+1][midx+1]=3;
            func(x,y,midx,midy,length);
            func(x,y+length,midx,midy+1,length);
            func(x+length,y+length,midx+1,midy+1,length);
            func(x+length,y,ax,ay,length);
        }
        else 
        {        
            map[midy][midx]=map[midy+1][midx]=map[midy][midx+1]=1;
            func(x,y,midx,midy,length);
            func(x,y+length,midx,midy+1,length);
            func(x+length,y,midx+1,midy,length);
            func(x+length,y+length,ax,ay,length);
        }
    }
}
void main()
{    
    int i,j;
    while(scanf("%d%d%d",&k,&n,&m)!=EOF)
    {
        memset(map,0,sizeof(map));
        n++;
        m++;
        map[n][m]=0;
        t=pow(2,k);
        func(1,1,m,n,t);
        map[n][m]=0;
        for(i=1;i<=t;i++)
        {
            for(j=1;j<=t;j++)
                printf("%d",map[i][j]);
            printf("\n");
        }
        printf("\n");
    }
}

 

 

 

 

 

 

posted @ 2012-11-07 14:53  Link_King_Jay  阅读(534)  评论(0编辑  收藏  举报