引用请注明出处: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 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;
}