UVa系列——101/The Blocks Problem

来源:互联网 发布:tcp编程实例 编辑:程序博客网 时间:2024/06/10 04:58

引用请注明出处:http://blog.csdn.net/int64ago/article/details/7419085

这题是个模拟题,不过开始不太好理解,把它想复杂了,其实也算个简单的模拟题,注意几点:

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 26struct 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;}


原创粉丝点击