跳棋jump
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
有一列无限长的格子里面(左右侧棋盘格子数均可无限延伸),某些格子里面放了棋子。如果某个格子里面有多于一颗棋子,就可以拿走这一颗,并且在这个格子的左边两个格子里面各放一颗。如果连续两个格子里面都有棋子,可以分别在两个格子里面各拿走一颗,并且在它们右边的格子里面放一颗。
现在的任务是:给定初始状态,要求使用以上操作,使得:1、每个格子至多只有1颗棋子2、没有相邻的两个格子都有棋子。简单的说,就是无法继续操作下去了!
-
输入
-
第一行给出N(0<N<=100),表示有N组测试数据
随后的每组测试数据的第一行给出棋子个数M(0<M<=10000)
接下来一行给出棋子摆放方法,0表示该格子没有棋子,其他数字表示相应格子有该数目的棋子。(有棋子的棋盘格子的总跨度不超过20)
输出
-
输出最终棋盘摆放方法,每组测试数据占一行。
从第一个有棋子的格子开始输出。
样例输入
-
2 4 0 0 1 0 0 2 0 0 1 3 0 0 0 0 0 3
样例输出
-
1 0 1 0 1
1 0 0 0 1
-
思路:守恒定理
-
//jump跳棋 #include <stdio.h> #include <math.h> #include <string.h> long long fb[100]; int in[10000], mark[500]; int main() { long long sum = 0, temp; int sp, ep, n, m, i, flag; fb[0] = 0; fb[1] = 1; for(i = 2; i < 62; i++) { fb[i] = fb[i-1] + fb[i-2]; } scanf("%d", &n); while(n--) { sum = sp = ep = 0; memset(in, 0, sizeof(in)); memset(mark, 0, sizeof(mark)); scanf("%d", &m); i = 100; sp = 2*log((double)m)/log(3.0)+5; while(m > 0) { scanf("%d", &in[i]); m -= in[i]; if(ep == 0 && in[i] != 0) { ep = i; } i++; } sp = ep - sp; ep = i; i = 1; while(sp <= ep) { sum += (in[sp]*fb[i]); sp++; i++; } temp = sum; i = 61; while(sum > 0) { if(sum >= fb[i]) { mark[i] = 1; sum -= fb[i]; } i--; } i = 1; flag = 0; while(temp > 0) { if(mark[i]) { flag = 1; temp -= fb[i]; } if(flag) { printf("%d ", mark[i]); } i++; } printf("\n"); } return 0; }
-
第一行给出N(0<N<=100),表示有N组测试数据