HDU 5336 XYZ and Drops (模拟+搜索,详解)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5336

题面:

XYZ and Drops

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 725    Accepted Submission(s): 201

Problem Description

XYZ is playing an interesting game called "drops". It is played on a
r?c
grid. Each grid cell is either empty, or occupied by a waterdrop. Each waterdrop has a property "size". The waterdrop cracks when its size is larger than 4, and produces 4 small drops moving towards 4 different directions (up, down, left and right).

In every second, every small drop moves to the next cell of its direction. It is possible that multiple small drops can be at same cell, and they won‘t collide. Then for each cell occupied by a waterdrop, the waterdrop‘s size increases by the number of the
small drops in this cell, and these small drops disappears.

You are given a game and a position (x,
y),
before the first second there is a waterdrop cracking at position (x,
y).
XYZ wants to know each waterdrop‘s status after T
seconds, can you help him?

1≤r≤100,
1≤c≤100,
1≤n≤100,
1≤T≤10000

Input

The first line contains four integers
r,
c,
n
and T.
n
stands for the numbers of waterdrops at the beginning.

Each line of the following n
lines contains three integers xi,
yi,
sizei,
meaning that the i-th
waterdrop is at position (xi,
yi)
and its size is sizei.
(1≤sizei≤4)

The next line contains two integers x,
y.

It is guaranteed that all the positions in the input are distinct.

Multiple test cases (about 100 cases), please read until EOF (End Of File).

Output

n
lines. Each line contains two integers Ai,
Bi:

If the i-th
waterdrop cracks in T
seconds, Ai=0,
Bi=
the time when it cracked.

If the i-th
waterdrop doesn‘t crack in T
seconds, Ai=1,
Bi=
its size after T
seconds.

Sample Input

4 4 5 10
2 1 4
2 3 3
2 4 4
3 1 2
4 3 4
4 4

Sample Output

0 5
0 3
0 2
1 3
0 1

Author

XJZX

Source

2015 Multi-University Training Contest 4

解题:

比赛的时候,卡在Walk out那题上了,看这道题又觉得题意不清晰,又怕超时,就没敢做,后面一个小时都在发呆,其实以后应该充分利用时间,不要太高估题目。往往最后一个小时才是最关键的。另外一只队伍最后一小时出了3题。

题目意思是,在给定的方格中的某些位置,有一些水团,当新加入水珠时,如果该水团的体积大于4,那么它就会变成4个体积为1的水珠,朝上下左右四个方向去。每1秒移动1格,当新水珠加入水团时,水团可能会因体积大于4而爆炸。还有,如果多个水珠同时到达一个格子,而该格子没有水团,那么这些水珠将继续前行,如果出了边界,便消失。

用bfs模拟水珠的运动,如果水珠加入一个水团,那么该水团的体积加一,并判断是否大于4,大于则分解成4个小水珠加入队列,并将该点体积清零。如果不大于,那么只是单纯的将体积加一,该水珠也就加入了水团,不再运动。同时需注意,因为可能一个水珠先到达水团,该水团就分解了,后续队列中又一水珠到达该处,如果之前分解的时候,不加标记,那么就会朝现在的水珠方向,多出一颗水珠,所以要加一个标记(用crack非零标记)。

一个位置是不可能分解两次的,因为只有初始有水团的地方,才能吸收水珠,进而分解,所以也无需考虑crack是否会重复或覆盖的问题。

总结:

要相信自己,基本上100人可以做的题目,那么都可以去尝试,也不用死抠复杂度,只要不是明显不可以的,而手头又空着,无题可做,那么就可以去大胆地敲。这题的模拟,其实比赛的时候觉得并不是很难,但因为过得只有100人,怕暴力模拟会超时,所以没做,事实证明46ms,实属遗憾啊!

代码:

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
int r,c,n,t,tx,ty;
//四个方向
int d[4][2]={0,1,-1,0,0,-1,1,0};
//运动的小水珠的方向,坐标和时间
struct node
{
  int dir,x,y,t;
};
//判断是否在边界内
bool Inside(int x,int y)
{
	if(x>=1&&x<=r&&y>=1&&y<=c)
		return true;
	return false;
}
//存储水团的位置
struct drop
{
	int x,y;
}store[105];
queue <node> qe;
//map记容量
int  map[105][105];
//crack记分解时间
int crack[105][105];
//模拟水珠运动
void bfs()
{
	int dir,ti,xx,yy;
	node tmp;
	while(!qe.empty())
	{
		//取当前节点
		tmp=qe.front();
		qe.pop();
		tx=tmp.x;
		ty=tmp.y;
		dir=tmp.dir;
		ti=tmp.t;
		//如果该点有水团
		if(map[tx][ty])
		{
			//体积加1
			map[tx][ty]++;
			//大于4,分解
			if(map[tx][ty]>4)
			{
				//记录分解时间
				crack[tx][ty]=ti;
				map[tx][ty]=0;
                for(int i=0;i<4;i++)
	            {
				 //四个方向
				 xx=tx+d[i][0];
		         yy=ty+d[i][1];
				 //在边界内
		         if(Inside(xx,yy))
		         {
                   tmp.x=xx;
			       tmp.y=yy;
			       tmp.t=ti+1;
			       tmp.dir=i;
				   //在时间T内
				   if(tmp.t<=t)
			       qe.push(tmp);
				 }
		        }
	         }
		}
		//该点原本就没有水团或者水团已经分解,但不是刚刚分解的,去除那个已经弹出的水珠的情况
		else if(crack[tx][ty]!=ti)
		{
            xx=tx+d[dir][0];
			yy=ty+d[dir][1];
			if(Inside(xx,yy))
			{
				tmp.x=xx;
				tmp.y=yy;
				tmp.t=ti+1;
				tmp.dir=dir;
				if(tmp.t<=t)
				qe.push(tmp);
			}
		}
	}
}
int main()
{
	int x,y,v;
	node tmp;
	while(~scanf("%d%d%d%d",&r,&c,&n,&t))
	{
       memset(map,0,sizeof(map));
	   memset(crack,0,sizeof(crack));
	   //读入
       for(int i=0;i<n;i++)
	   {
		   scanf("%d%d%d",&store[i].x,&store[i].y,&v);
		   map[store[i].x][store[i].y]=v;
	   }
	   scanf("%d%d",&x,&y);
	   //初始点分解
	   for(int i=0;i<4;i++)
	   {
          tx=x+d[i][0];
		  ty=y+d[i][1];
		  if(Inside(tx,ty))
		  {
            tmp.x=tx;
			tmp.y=ty;
			tmp.t=1;
			tmp.dir=i;
			qe.push(tmp);
		  }
	   }
	   //模拟
	   bfs();
	   //输出
	   for(int i=0;i<n;i++)
	   {
         if(crack[store[i].x][store[i].y])
			 printf("0 %d\n",crack[store[i].x][store[i].y]);
		 else
			 printf("1 %d\n",map[store[i].x][store[i].y]);
	   }
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-29 05:29:44

HDU 5336 XYZ and Drops (模拟+搜索,详解)的相关文章

Hdu 5336 XYZ and Drops (bfs 模拟)

题目链接: Hdu 5336 XYZ and Drops 题目描述: 有一个n*m的格子矩阵,在一些小格子里面可能会有一些水珠,每个小水珠都有一个size.现在呢,游戏开始咯,在一个指定的空的小格子里面有一个将要向四周爆裂的水珠,在下一面分别向上,下,左,右四个方向发射一个小水滴,(小水滴与水珠同,小水滴没有size),当小水滴走向一个格子,这个格子如果是空或者有其他的小水滴同时走到这个格子的情况下,对小水滴的运动轨迹是不影响的.但是遇到水珠的话,小水滴就会被吸收,水珠每次吸收一个小水滴size

HDU 5336——XYZ and Drops——————【广搜BFS】

XYZ and Drops Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1250    Accepted Submission(s): 407 Problem Description XYZ is playing an interesting game called "drops". It is played on a r∗

HDU 5336 XYZ and Drops(模拟十滴水游戏 BFS啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5336 Problem Description XYZ is playing an interesting game called "drops". It is played on a r?c grid. Each grid cell is either empty, or occupied by a waterdrop. Each waterdrop has a property &quo

hdu 5336 XYZ and Drops 【BFS模拟】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5336 题意:给你一个r*c的网格,有的网格为空,有的有水,再给出一个爆炸点,从这个点向四周爆出四个水滴,若碰到水则融为一体,若碰到其他水滴直接跑过去互不影响,每秒可跑一格,若水中水滴数量超过4则爆开,问T秒后网格的状态是怎样的. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <li

hdu5336 XYZ and Drops (模拟+vector删除第i个元素)

题目链接: hdu5336 XYZ and Drops 模拟题一道,比较水,但是因为题意曲折 顺带vector的删除操作也是不太明白 总之逗了很长时间 删除第i个元素 v.erase(v.begin() + i); 删完后后面的元素都会往前移一个,所以下一个元素还是v[i] 也可以下面这样 it = v.erase(it); //erase()返回值是指向下一个元素的指针 //#define __LOCAL //#define __LLD #include <stdio.h> #include

poj3279搜索详解

这道搜索题和大部分的题都不太一样,没有一个明显的思路,格子间的状态都是互相影响的,只能通过枚举第一行,逐行往下搜. 详解: 1.如何搜索:如果从上到下搜索,当前行是否需要反转取决于上一行的状态,通过翻转当前行使上一行为0,而不是通过上一行翻转为0后,看当前行的状态判断自己是否需要翻转,否则还会继续影响上一行.所以枚举一下第一行所有的状态,搜索到最后一行结束,如果可以保证最后一行都是0,那么方案可以,否则重新定义第一行的状态,继续搜索,找出使反转次数最少的方案. 2.保证字典序最小:按照字典序从小

HDU 5336多校 十滴水模拟

Problem Description XYZ is playing an interesting game called "drops". It is played on a r?c grid. Each grid cell is either empty, or occupied by a waterdrop. Each waterdrop has a property "size". The waterdrop cracks when its size is

Android单元测试与模拟测试详解

测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabricator differential 发diff时提交需要执行的单元测试,在开发流程上就可以保证远端代码的稳定性). 2. 测什么? 一般单元测试: 列出想要测试覆盖的异常情况,进行验证. 性能测试. 模拟测试: 根据需求,测试用户真正在使用过程中,界面的反馈与显示以及一些依赖系统架构的组件的应用测

HDU 4049 Tourism Planning (状压dp 详解)

Tourism Planning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1125    Accepted Submission(s): 487 Problem Description Several friends are planning to take tourism during the next holiday. Th