HDU5336题解

来源:互联网 发布:淘宝砖石卖家信誉好吗 编辑:程序博客网 时间:2024/06/17 01:20

解题思路

这题思路并不难,主要问题是,不太好编码实现(可能是本人练习不够吧),因为有个时间在里面,而且每个小水滴都同时流动,感觉好复杂的样子。比赛时,我首先想到的是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;}

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

原创粉丝点击