这题是个模拟题,不过开始不太好理解,把它想复杂了,其实也算个简单的模拟题,注意几点:
1、注意4个动作的区别与联系,尽量把重复的动作模块化,减少代码量,比如我用了return_back这个函数来处理returning any blocks to their initial positions.
2、注意题目输入非法的条件是什么,说白了就是两个数不能在同一列(两数相同包含在这种情况中)!
3、为了时间效率更高,需要实时记录每个木块位置,这个是8msAC的,如果每次移动前才确定位置就要全部扫一遍,这个效率是很低的,比实时的要慢好几倍!
4、字符串要定义成字符数组的形式,因为是不能对一个指针用scanf(除非malloc了),指针可以被一个字符串初始化,但是绝对不能等价,其中存在隐式转换!
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NUM 26 struct Pos{ int pos_x; int pos_y; }; int block_num; /* 总的木块数 */ int pos_num[MAX_NUM]; /* 每个位置上的木块数 */ int pos_map[MAX_NUM][MAX_NUM];/* 任意位置上木块的标号 */ struct Pos block_pos[MAX_NUM]; /* 全局实时记录木块所在的位置 */ /* * 根据输入的木块数进行初始化 * 其中,都是上面定义的量 */ void init_pos() { int i; for(i = 0; i != block_num; ++i){ pos_num[i] = 1; pos_map[i][0] = i; block_pos[i].pos_x = i; block_pos[i].pos_y = 0; } } /* * 把(posx,posy)这个位置上的木块 * 上面的木块恢复到原来的位置 */ void return_back(int posx, int posy) { int i; for(i = pos_num[posx] - 1; i != posy; --i){ int tmp = pos_map[posx][i]; int j; for(j = pos_num[tmp] - 1; j >= 0; --j){ pos_map[tmp][j+1] = pos_map[tmp][j]; ++block_pos[pos_map[tmp][j]].pos_y; } pos_map[tmp][0] = tmp; ++pos_num[tmp]; --pos_num[posx]; block_pos[tmp].pos_x = tmp; block_pos[tmp].pos_y = 0; } } void move_onto(int a, int b) { //if(a == b) return ; /* 取得a,b的当前位置,下同 */ int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y; int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y; if(posax == posbx) return ; return_back(posax, posay); return_back(posbx, posby); pos_map[posbx][posby + 1] = a; block_pos[a].pos_x = posbx; block_pos[a].pos_y = posby + 1; ++pos_num[posbx]; --pos_num[posax]; } void move_over(int a, int b) { //if(a == b) return ; int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y; int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y; if(posax == posbx) return ; return_back(posax, posay); pos_map[posbx][pos_num[posbx]] = a; block_pos[a].pos_x = posbx; block_pos[a].pos_y = pos_num[posbx]; ++pos_num[posbx]; --pos_num[posax]; } void pile_onto(int a, int b) { //if(a == b) return ; int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y; int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y; if(posax == posbx) return ; return_back(posbx, posby); int i, cnt; for(i = posay, cnt = 1; i != pos_num[posax]; ++i, ++cnt){ pos_map[posbx][posby + cnt] = pos_map[posax][i]; block_pos[pos_map[posax][i]].pos_x = posbx; block_pos[pos_map[posax][i]].pos_y = posby + cnt; } pos_num[posax] -= cnt - 1; pos_num[posbx] += cnt - 1; } /* * 这个与pile_onto的区别只有两点: * 1、不需要return_back b上面的木块 * 2、移动到b上的起始位置从顶部开始了 */ void pile_over(int a, int b) { //if(a == b) return ; int posax = block_pos[a].pos_x, posay = block_pos[a].pos_y; int posbx = block_pos[b].pos_x, posby = block_pos[b].pos_y; if(posax == posbx) return ; int i, cnt; for(i = posay, cnt = 0; i != pos_num[posax]; ++i, ++cnt){ pos_map[posbx][pos_num[posbx] + cnt] = pos_map[posax][i]; block_pos[pos_map[posax][i]].pos_x = posbx; block_pos[pos_map[posax][i]].pos_y = pos_num[posbx] + cnt; } pos_num[posax] -= cnt; pos_num[posbx] += cnt; } int main(int argc, char *argv[]) { scanf("%d", &block_num); init_pos(); char action[10], what[10]; /* 这里不能定义为指针,否则段错误 */ int a, b; while(scanf("%s",action) != EOF && (strcmp(action,"quit") != 0)){ scanf("%d%s%d", &a, what, &b); if(strcmp(action,"move") == 0 && strcmp(what,"onto") == 0){ move_onto(a, b); } if(strcmp(action,"move") == 0 && strcmp(what,"over") == 0){ move_over(a, b); } if(strcmp(action,"pile") == 0 && strcmp(what,"onto") == 0){ pile_onto(a, b); } if(strcmp(action,"pile") == 0 && strcmp(what,"over") == 0){ pile_over(a, b); } } int i; for(i = 0; i != block_num; ++i){ printf("%d:", i); int j; for(j = 0; j != pos_num[i]; ++j ){ printf(" %d",pos_map[i][j]); } putchar('\n'); } return 0; }