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
#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"); } }