CCF-201604-2-俄罗斯方块

问题描述
试题编号: 201604-2
试题名称: 俄罗斯方块
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游戏。
  游戏在一个15行10列的方格图上进行,方格图上的每一个格子可能已经放置了方块,或者没有放置方块。每一轮,都会有一个新的由4个小方块组成的板块从方格图的上方落下,玩家可以操作板块左右移动放到合适的位置,当板块中某一个方块的下边缘与方格图上的方块上边缘重合或者达到下边界时,板块不再移动,如果此时方格图的某一行全放满了方块,则该行被消除并得分。
  在这个问题中,你需要写一个程序来模拟板块下落,你不需要处理玩家的操作,也不需要处理消行和得分。
  具体的,给定一个初始的方格图,以及一个板块的形状和它下落的初始位置,你要给出最终的方格图。
输入格式
  输入的前15行包含初始的方格图,每行包含10个数字,相邻的数字用空格分隔。如果一个数字是0,表示对应的方格中没有方块,如果数字是1,则表示初始的时候有方块。输入保证前4行中的数字都是0。
  输入的第16至第19行包含新加入的板块的形状,每行包含4个数字,组成了板块图案,同样0表示没方块,1表示有方块。输入保证板块的图案中正好包含4个方块,且4个方块是连在一起的(准确的说,4个方块是四连通的,即给定的板块是俄罗斯方块的标准板块)。
  第20行包含一个1到7之间的整数,表示板块图案最左边开始的时候是在方格图的哪一列中。注意,这里的板块图案指的是16至19行所输入的板块图案,如果板块图案的最左边一列全是0,则它的左边和实际所表示的板块的左边是不一致的(见样例)
输出格式
  输出15行,每行10个数字,相邻的数字之间用一个空格分隔,表示板块下落后的方格图。注意,你不需要处理最终的消行。
样例输入
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 0 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1
0 0 0 0
3
样例输出
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 1 0 0 0 0


解题思路:
当时测试的时候用的是dfs过的,写的比较麻烦,虽然满分过了,但不推荐。用最直接的方法重新写了一下。把板块图案输入进来之后,找哪些方块是最底面的,当然是那四个里面的处于最底层的。为了判断是不是最底层的,开数组的时候多开了一层,直接判断下面是不是0就知道是不是最底层的。然后根据题目中给出的最后一个数,先把列进行了偏移的调整。然后计算行数的偏移量是多少。直接找到最底层的方块,向下探索,遇到1,说明偏移量就是两者之差-1。没有遇到的话就是当前方块到最底层的距离。然后再这些距离中找到最小值就是行数的偏移量,直接在输入的矩阵里面进行修改就可以了,最后打印输出。




源代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int main()
{
	int g[15][10];
	int c[5][4];//图案
	int i,j,k;
	int pos;
	int base;//偏移量
	int mindis;
	int x[4],y[4],flag[4],dis[4];
	memset(g,0,sizeof(g));
	memset(c,0,sizeof(c));
	memset(dis,100,sizeof(dis));
	memset(flag,0,sizeof(flag));
	memset(x,0,sizeof(x));
	memset(y,0,sizeof(y));
	k=0;
	mindis = 100;
	for(i=0;i<15;i++)
	{
		for(j=0;j<10;j++)
		{
			scanf("%d",&g[i][j]);
		}
	}
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			scanf("%d",&c[i][j]);
			if(c[i][j]==1)
			{
				x[k]=i;
				y[k]=j;
				k++;
			}
		}
	}
	scanf("%d",&pos);
	base = pos-1;//因为保存的时候下标是从0开始的
	for(i=0;i<4;i++)
	{
		if(c[x[i]+1][y[i]]==0)//判断是不是最底层的方块
		{
			flag[i]=1;
		}
	}
	for(i=0;i<4;i++)
	{
		y[i]+=base;
		if(flag[i])
		{
			for(j=x[i]+1;j<15;j++)
			{
				if(g[j][y[i]]==1)
				{
					dis[i]=j-x[i]-1;//计算底层方块到碰见另一个方块时的垂直距离
					break;
				}
			}
			if(j==15)
			{
				dis[i]=14-x[i];//没有碰到就是到最底层的垂直距离
			}
			mindis=min(mindis,dis[i]);//所有距离值求最小值就是行数偏移量
		}
	}
	for(i=0;i<4;i++)
	{
		x[i]+=mindis;
		g[x[i]][y[i]]=1;
	}
	for(i=0;i<15;i++)
	{
		for(j=0;j<9;j++)
		{
			printf("%d ",g[i][j]);
		}
		printf("%d\n",g[i][j]);
	}
	return 0;
}


posted @ 2017-11-03 01:43  lemonsbiscuit  阅读(157)  评论(0编辑  收藏  举报