SGU 109 Magic of David Copperfield II 翻译 题解

109. Magic of David Copperfield II

每个数据时间限制: 0.50 sec. 
每个数据内存限制: 4096 KB

 

著名的魔术师大卫科波菲尔喜欢表演下面的魔术:一个N行N列不同图片的矩阵出现在大屏幕上,我们给所有的图片这样命名:

 

1 2 ... N
... ... ... ...
N*(N-1)+1 N*(N-1)+2 ... N*N

 

每一个参与的观众被要求将手指放在左上方的图片上(即编号为1的图片),魔术师开始了:魔术师告诉观众在图片上移动k次(移动是把手指放到上下左右相邻的图片上,如果那儿有图片的话),然后他(魔术师)的手微微一指(指向一些图片)并说:“你不在这里”,然后……是真的!你的手指没有指向任何一个被删除的图片(指向的图片)然后再来一次,他告诉观众再移动K2次……以此类推。在最后,他删除到只剩最后一个图片了,然后胜利地微笑着宣布“我抓到你了!”(掌声)。

现在,大卫准备再表演一次这个魔术。不幸的是,他这几天头疼,你知道头疼的时候变戏法有多难!所以你必须写一个程序来帮组大卫变魔术。

 

输入:

输入文件包含一个整数N (1<N<101).

 

输出:

你的程序需要像下面这样输出数字:
K1 X1,1 X1,2 ... X1,m1
K2 X2,1 X2,2 ... X2,m2
...
Ke Xe,1 Xe,2 ... Xe,me
Ki是观众第i次移动的步数(N<=Ki<=300),所有Ki都要互补不相同(即当i<>j时,满足Ki<>Kj)Xi,1 Xi,2 ... Xi,mi 是在观众进行了Ki次移动之后大卫需要删除的图片(图片数字的顺序是任意的,但是每个图片只能列出一次,并且每回至少删除一张图片)。
每一回的描述都要在一个新行里。每一行的数字都要使用一个或多个空格分隔开。循环了e次之后,只剩下一个图片没有被删除。

 

样例输入:

3

 

样例输出:

3 1 3 7 9
5 2 4 6 8

================================华丽的分割线 ================================

  (待添加题解 2011年6月10日 19:10:51)

  2011年6月10日 21:59:17。
  做了这个题目我清楚的认识到了,在考试时做题目要冷静,这种题目关乎矩阵的就先画一个图,然后慢慢分析!也学一个乖,这种在矩阵上相邻的位置移动的,就要分奇数格和偶数格。
  http://www.docin.com/p-212303829.html,很不错的题解!特别是那几幅图!还有,我的代码是参考一个大牛的,本来我是按照那个题解的方案二写的,但是出现的问题就是最终k>300,然后就WA了!
  这里的优化技巧是,第一次移动就是N,然后从(3,n)为左上角,斜着的一条线下面的整个三角形都可以放在第一次移动,这样直接减少了一般的移动次数,然后再用上面那个链接的方案二。

#include <stdio.h>
#include <stdlib.h>
int tot;
int n;

//从右上角(x, y)向左下角输出
void output(int x, int y, int end)
{
	if(x > n || y < 1){
		if(end){
			printf("\n");
		}
		return;
	}
	printf(" %d", (x - 1) * n + y);
	output(x + 1, y - 1, end);
}

int main(int argc, char **argv)
{
	int i, k;
	scanf("%d", &n);
	//有点麻烦的特殊情况, 直接..作弊算了
	if(n == 2){
		printf("3 4\n5 2 3\n");
		return 0;
	}
	printf("%d", n);
	for(i = 3; i <= n; i++){
		output(i, n, 0);
	}
	if(n & 1){
		k = n + 2;
	}else{
		k = n + 1;
	}
	printf("\n%d", k);
	output(2, n, 1);
	for(i = n; i >= 2; i--){
		k += 2;
		printf("%d", k);
		output(1, i, 1);
	}
	return 0;
}

posted @ 2011-06-10 18:17  zqynux  阅读(386)  评论(0编辑  收藏  举报