解题思路

这题思路并不难,主要问题是,不太好编码实现(可能是本人练习不够吧),因为有个时间在里面,而且每个小水滴都同时流动,感觉好复杂的样子。比赛时,我首先想到的是DFS+时间流做参数,由于比赛时神经紧张,思路比较混乱,没写出来,放弃了。比赛结束后,冷静下来思考后,这题应该用BFS更合适,只要在“水滴”这个结构体中定义时间参数就好。对于这种带“时间”运动的典型题型,用BFS更合适。代码结构和思路和常规的BFS基本一样,而且都不用循环扫描4个方向,因为小水滴是一路向前走的。

注意

1、如果两个小水滴相遇,不是形成水坑,而是擦肩而过(注定它俩没缘分......)。比赛时心里总想着看题速度要快,然后主观臆断,认为两个小水滴相遇会形成大小为1+1=2的水坑,导致理解错题目意思。。。。。。。看再快也是白搭。所以,磨刀不误砍柴工,看题一定要仔细,理解清楚题目意思,否则一切都是瞎扯淡。

2、如果多个水滴同时到达一个水坑,那么,如果水坑爆炸,这多个水滴都会连带进去消失。比如:如果原水坑大小为4,有3个水滴同时过来,那么,他们合在一起再爆炸,分解成4小水滴。也就是:(4+3)/4 = 1。因为程序执行是单线程的,逻辑上同时到达同一个位置的水滴在执行时时间不一致,所以需要考虑这么一种情况。也就是说,当A水滴到达水坑W后,W爆炸,分解成4个不同方向的小水滴。然后B水滴(到达水坑W的时间和A相同)也流到水坑W时,逻辑上他和A应该时一起进入W然后爆炸的,但是如果不判断,那么,B水滴会继续向前流,这就不对了。

片花:果然“水坑”题是又水又坑。。。。。。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;

const int dirs[][2] = {{0, -1}, {0, 1}, { -1, 0}, {1, 0}};
typedef struct {
    int x, y;
} Water;//水坑
typedef struct {
    int x, y, t, dir;
} Drop;//水滴
int r, c, n, t;
Drop st[4];
/*sz[x][y]:坐标(x, y)位置的水坑的大小。boom[x][y]:坐标(x, y)位置的水坑爆炸的时间。*/
int sz[110][110], boom[110][110];
vector<Water> ds;
queue<Drop> que;

void bfs() {
    while(!que.empty())que.pop();
    for(int i = 0; i < 4; i++)que.push(st[i]);
    while(!que.empty()) {
        Drop d = que.front();
        que.pop();
        /*这个地方:continue和return都行。
        为什么呢?continue表示对队列中剩余的小水滴也依次处理。
        因为我们用的是BFS,如果当前小水滴d的生存时间为t了,
        那么,后面的小水滴肯定为t(因为t+1也是由t推出的。而水滴生存时间到了t就不能再流动了)。
        所以后面的小水滴同样会做这个处理。
        而return直接结束BFS,因为实际上后面的操作都是没必要的。
        然而:HDUOJ上实测,continue运行时间31ms,return运行时间46ms.
        */
        if(d.t >= t)continue;
        int nx = d.x + dirs[d.dir][0], ny = d.y + dirs[d.dir][1];
        /*前4个条件判断越界,最后一个条件是考虑这种情况:
            两个或多个水滴同时向一个水坑流去,那么,如果水坑爆炸了,
            boom[nx][ny] == d.t + 1。由于我们的程序执行是单线程的,
            逻辑上时间相同而实际上代码运行时的时间不同。所以,这个条件就是说,
            对于当前水滴的后几个水滴(这几个水滴到达(nx, ny)这个水坑的时间相同),
            如果(nx, ny)这个位置的水坑爆炸了,那么,逻辑上,当前水滴的后几个水滴
            都应该是连带进去爆炸的。因为他们到达这个水坑的时间相同。
        */
        if(nx < 1 || nx > r || ny < 1 || ny > c || boom[nx][ny] == d.t + 1)continue;
        if(sz[nx][ny] > 0) {
            sz[nx][ny]++;
            if(sz[nx][ny] > 4) {
                boom[nx][ny] = d.t + 1;
                /*分解成4个方向的水滴。*/
                for(int i = 0;i < 4;i++)que.push((Drop) {nx, ny, d.t + 1, i});
                sz[nx][ny] = 0;
            }
        }
        /*小水滴继续向前流*/
        else que.push((Drop) {nx, ny, d.t + 1, d.dir});
    }
}

void init() {
    ds.clear();
    memset(sz, 0, sizeof(sz));
    memset(boom, -1, sizeof(boom));
}

int main() {
    int x, y, szz;
    while(scanf("%d%d%d%d", &r, &c, &n, &t) != EOF) {
        init();
        for(int i = 0; i < n; i++) {
            scanf("%d%d%d", &x, &y, &szz);
            sz[x][y] = szz;
            ds.push_back((Water) {x, y});
        }
        scanf("%d%d", &st[0].x, &st[0].y);
        st[0].t = 0, st[0].dir = 0;
        for(int i = 1; i < 4; i++) {
            st[i] = st[0];
            st[i].dir = i;
        }
        bfs();

        Water w;
        for(int i = 0; i < ds.size(); i++) {
            w = ds[i];
            if(boom[w.x][w.y] >= 0)printf("0 %d\n", boom[w.x][w.y]);
            else printf("1 %d\n", sz[w.x][w.y]);
        }
    }
    return 0;
}

加油,不要怕,相信自己一定可以的!

HDU5336题解的更多相关文章

  1. hdu5336 Walk Out

    hdu5336 Walk Out 题意是:入口:地图的左上角,出口,地图的右上角,求所经过的路径的二进制数最小 照着题解敲了一遍 思路是:首先 二进制 的 位数 越小 越好,其次 二进制的前缀零越多 ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  4. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  9. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

随机推荐

  1. 利用Appium Python测试爱壁纸的登录和设置壁纸

    设置壁纸: #coding:utf-8 #Import the common package import os import unittest from appium import webdrive ...

  2. diff和patch 打补丁

    在Linux环境下,有两个工具用来给project打补丁,即diff和patch diff         diff具有比较功能.可以使用man命令查看其使用方法. NAME        diff ...

  3. Python程序员不完全指南

    Python 基础 Python基础 基础数据类型 深浅copy 文件操作 函数 初识函数 函数进阶 装饰器函数 迭代器和生成器 各种推导式 递归函数 内置函数和匿名函数 异常处理 常用模块 模块和包 ...

  4. SpringMVC札集(07)——JSON数据

    自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onL ...

  5. 深度学习(七十)darknet 实现编写mobilenet源码

    一.添加一个新的网络层 (1)parse.c文件中函数string_to_layer_type,添加网络层类型解析: if (strcmp(type, "[depthwise_convolu ...

  6. PDF文档过期时间/自毁设置

    不是很完美的方法,可以凑活着用: 切换到Pages预览页,右击页面选页面属性 切换到Action,选Run a Javascript,代码: // PDF JavaScript to make it ...

  7. 关于解决Springboot跨域请求的方法

    前言 最近在项目中,由于前后分离,前台项目和后台项目部署的不在一台服务器,就产生了跨域的问题,特此记录下 正文 正常情况下,如果提示: 就可以判断是没有解决跨域的问题了. 在SSM中,我曾经这样解决过 ...

  8. 将 UWP 的有效像素(Effective Pixels)引入 WPF

    在很久很久以前,WPF 诞生之初,有一个神奇的单位,它的名字叫做——设备无关单位(DIP,Device Independent Unit).微软给它描绘了一片美好的愿景——在任何显示器上显示的尺寸是相 ...

  9. java集成WebSocket向指定用户发送消息

    一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通 ...

  10. LeetCode 529. Minesweeper

    原题链接在这里:https://leetcode.com/problems/minesweeper/description/ 题目: Let's play the minesweeper game ( ...