UVa系列——101/The Blocks Problem

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


你可能感兴趣的:(struct,action,returning)