SGU 109.Magic of David Copperfield II
时间: 0.50 sec
空间: 4096 KB
题目
著名的魔术师大卫-科波菲尔喜欢表演这样一个小魔术: N*N个不同图案构成N行N列的表格在电视上出现,我们为了方便研究,把这些格子编号:
1 2 ... N
... ...
... ...
N*(N-1)+1 N*(N-1)+2 ... N*N
所有观众首先将手指指向左上角的小格(1号图案)然后魔术开始:魔术师命令观众在图案中移动手指 K1次(一次移动是指移动到当前图案上下左右的另一个图案),之后魔术师轻挥手指,有一些图案所在的格子不见了(被删掉的格子以后不能经过),魔术师解释说"你不可能在这里!", ....他说对了 - 你的手指并不在他删掉的任一格子上。接着他再让观众移动手指K2次, 等等. 最后他删得只剩下1个格子,面带微笑地宣布胜利 "我抓到你了!" (鼓掌....).
就在刚才,魔术师又想完一次这个小把戏。不幸的是,他昨天很累,你了解当人在头痛的时候变戏法是很困难的。你需要编写一个程序来帮助科波菲尔完成这个小魔术。
输入
包括一个整数 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 次移动后科波菲尔需要删掉的图案编号(每次删除的图案个数任意,但是每个图案不能不能被删除两次,每一轮必须删掉至少1个图案)。每一个新轮回必须占一个新行。整数间都用空格隔开,且最后只能留下一个图案。
样例输入
3
样例输出
3 1 3 7 9
5 2 4 6 8
{=====================}
分析
先提取一些要点:
- 只能上下左右移动,说明其奇偶性(就像国际象棋的棋盘,黑白块)
- 300>ki>=n (开始我没注意到这点,OJ反馈的信息是 PE。。。结果误会又PE几次)
- 每次都必须删掉一些格子
- 最后只剩一个格子
从上面看来,还是比较简单的,
假设认为棋盘G[i][j],当i+j的和为奇数时,称为奇块,和为偶数时称为偶块;
所有的从G[1][1],开始那么移动奇数次,必定是从一个偶块,移动到了一些奇块上。
那么只有以特定的方法在移动在一中格子上后,删除一些奇偶性不同的格子。
这里提供两种方法
第一种从右下角往左上角删
5 | ||||
5 | 4 | |||
5 | 4 | 3 | ||
5 | 4 | 3 | 2 | |
5 | 4 | 3 | 2 | 1 |
数字代表删的顺序,k从不小于n奇数开始,不断加2,不会超过300,这样删最后留下的是G[1][1];
=======================
第二种从四周删
1 | 2 | 1 | 2 | 1 |
2 | 2 | |||
1 | 1 | |||
2 | 2 | |||
1 | 2 | 1 | 2 | 1 |
输出的将结果和样例一样
最后留下的是中间的格子,可以用递归的方法,不断缩小n
例如上面n=5,在两次删除过后,中间留下了3*3的矩阵
要注意的是当n==2 时需要同方法那样特殊处理
如下
1 | 2 |
2 |
参考代码
方法一:
#include <iostream> using namespace std; int main(){ int N; cin>>N; int K=N; if(k>2)cout<<K; for (int x=1;x<=N;x++) for (int y=1;y<=N;y++) if (x+y>=N+3) cout<<" "<<(x-1)*N+y; if(k>2)cout<<endl; for (int XpY=N+2;XpY>2;XpY--){ while ((++K)%2==0); cout<<K; for (int x=1;x<=N;x++) for (int y=1;y<=N;y++) if (x+y==XpY) cout<<" "<<(x-1)*N+y; cout<<endl; } return 0; }
================================
方法二:
#include <cstdio> int n, p,k; void make (int t, int x, int k) { if (x==2) { int i=(t-1)*n+t; printf ("%d %d\n", k, i); printf ("%d %d %d\n", k+2, i+ 1, i + n); } else { printf ("%d", k); for (int i = t; i < t + x; i++) for (int j = t; j < t + x; j++) { if ( ((i + j) & 1) == 0 && (i == t || i == t + x - 1 || j == t || j == t + x - 1) ) printf (" %d", (i - 1) * n + j); } printf ("\n%d", k + 2); for (int i = t; i < t + x; i++) for (int j = t; j < t + x; j++) { if ( ((i + j) & 1) == 1 && (i == t || i == t + x - 1 || j == t || j == t + x - 1) ) printf (" %d", (i - 1) * n + j); } putchar (10); if (x - 2 > 1) make (t+1, x - 2,k+4); } } int main() { scanf("%d",&n); if (n & 1) k=n; else k=n+1; make (1, n, k); return 0; }
http://www.cnblogs.com/keam37/ keam所有 转载请注明出处