2015 多校赛 第四场 1010 (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 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

题意:

在一个 r*c 的格子图上,有 n 个水滴静止。每当水滴体积超过 4 时,会分成 4 个体积为 1 的小水滴向上下左右四个方向运动,每秒移动一个格子。小水滴与静止的水滴碰撞后会合成,体积相加。开始时 n 个水滴都静止,给出一个在 (x,y) 位置炸开的水滴作为启动源。

注意:1.小水滴彼此间不影响,即使同时经过同一位置。

2.若多个小水滴同时到达同一格子,则都与位于该格子的水滴合体,体积相加。超过 4 后按上述规则分裂。(即使为6,7等等)

思路:

因为数据较小所以直接暴力模拟O(nT)也能过。。

笔者用优先队列维护最先受到影响的水滴,依次处理,直到时间超出 T 或者是优先队列为空,则终止。

刚开始没有注意到应该注意的两点各种跪。。

水滴的结构体中还有一个变量 dir 记录该影响移动的方向。因为存在到了该“影响”发生的时候原有位置的水滴已经分裂不存在的情况,此时应继续向该方向搜索离之最近的点。

感觉实现的时候还是比较多细节要注意的。

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define mod 1005
const int U=1,D=2,L=3,R=4;
int r,c,n,t,x,y;
struct drop{
    int x,y,size,status,time,num,dir;
    bool operator < (const drop d) const{
        return time>d.time;
    }
}drops[105];
int update(int num,int dir){
    int closest=-1;
    for(int i=0;i<n;i++) if(drops[i].status&&i!=num){
        if(dir==U){
            if(drops[num].x==drops[i].x&&drops[num].y<drops[i].y)
                if(closest==-1||drops[i].y<drops[closest].y) closest=i;
        }
        else if(dir==D){
            if(drops[num].x==drops[i].x&&drops[num].y>drops[i].y)
                if(closest==-1||drops[i].y>drops[closest].y) closest=i;
        }
        else if(dir==L){
            if(drops[num].y==drops[i].y&&drops[num].x>drops[i].x)
                if(closest==-1||drops[i].x>drops[closest].x) closest=i;
        }
        else{
            if(drops[num].y==drops[i].y&&drops[num].x<drops[i].x)
                if(closest==-1||drops[i].x<drops[closest].x) closest=i;
        }
    }
    return closest;
}
priority_queue<drop>pq;
vector<drop> T;
int main(){
    for(int i=0;i<105;i++) drops[i].num=i;
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(~scanf("%d%d%d%d",&r,&c,&n,&t)){
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&drops[i].x,&drops[i].y,&drops[i].size);
            drops[i].status=1,drops[i].time=10005;
        }
        scanf("%d%d",&x,&y);
        while(!pq.empty()) pq.pop();
        drops[100].x=x,drops[100].y=y,drops[100].status=1;
        drops[100].size=4,drops[100].time=0;
        pq.push(drops[100]);
        int t_now=0;
        while(!pq.empty()){
            drop tmp=pq.top();
            while(!drops[tmp.num].status){
                pq.pop();
                int num=update(tmp.num,tmp.dir);
                if(num!=-1){
                    drop temp=drops[num];
                    temp.dir=tmp.dir;
                    if(temp.dir==U) temp.time=temp.y-tmp.y;
                    else if(temp.dir==D) temp.time=tmp.y-temp.y;
                    else if(temp.dir==L) temp.time=tmp.x-temp.x;
                    else temp.time=temp.x-tmp.x;
                    temp.time+=tmp.time;
                    pq.push(temp);
                }
                if(pq.empty()) break;
                else tmp=pq.top();
            }
            if(pq.empty()) break;
            if(tmp.time>t) break;
            int up=-1,down=-1,left=-1,righ=-1;
            if(drops[tmp.num].size<4){
                drops[tmp.num].size++;
                pq.pop();
                continue;
            }
            pq.pop();//new
            T.clear();
            while(!pq.empty()){
                drop Tmp=pq.top();
                if(Tmp.time==tmp.time&&Tmp.x==tmp.x&&Tmp.y==tmp.y)
                    pq.pop();
                else if(Tmp.time==tmp.time){
                    T.push_back(Tmp);
                    pq.pop();
                }
                else break;
            }
            for(int i=0;i<T.size();i++) pq.push(T[i]);
            drops[tmp.num].status=0;
            drops[tmp.num].time=tmp.time;
            t_now=drops[tmp.num].time;
            for(int i=0;i<n;i++) if(drops[i].status){
                if(tmp.x==drops[i].x){
                    if(tmp.y<drops[i].y){
                        if(up==-1||drops[i].y<drops[up].y) up=i;
                    }
                    else{
                        if(down==-1||drops[i].y>drops[down].y) down=i;
                    }
                }
                else if(tmp.y==drops[i].y){
                    if(tmp.x>drops[i].x){
                        if(left==-1||drops[i].x>drops[left].x) left=i;
                    }
                    else{
                        if(righ==-1||drops[i].x<drops[righ].x) righ=i;
                    }
                }
            }
            if(up!=-1&&drops[up].time>drops[up].y-tmp.y+t_now){
                drop temp=drops[up];
                temp.time=drops[up].y-tmp.y+t_now,temp.dir=U;
                pq.push(temp);
            }
            if(down!=-1){
                drop temp=drops[down];
                temp.time=tmp.y-drops[down].y+t_now,temp.dir=D;
                pq.push(temp);
            }
            if(left!=-1){
                drop temp=drops[left];
                temp.time=tmp.x-drops[left].x+t_now,temp.dir=L;
                pq.push(temp);
            }
            if(righ!=-1){
                drop temp=drops[righ];
                temp.time=drops[righ].x-tmp.x+t_now,temp.dir=R;
                pq.push(temp);
            }
            //pq.pop();
        }
        for(int i=0;i<n;i++){
            if(drops[i].status) printf("1 %d\n",drops[i].size);
            else printf("0 %d\n",drops[i].time);
        }
    }
    return 0;
}

时间: 2024-10-17 16:23:27

2015 多校赛 第四场 1010 (hdu 5336)的相关文章

2015 多校赛 第五场 1010 (hdu 5352)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5352 看题看得心好累. 题目大意: 给出 n 个点,依次执行 m 次操作:输入“1 x”时,表示将与 x 连通的点全部修复:输入“2 x y”,表示在 x 与 y 之间加一条边:输入“3 x y”,表示删除 x 与 y 之间的边.题目确保不会与重边并且操作合法. 题目会给出 k,要求每次修复的的点的数目小于等于k. 问:怎样执行操作1,使得令修复点数最多的同时,令每次执行操作1所修复的点的数目所构成

2015 多校赛 第四场 1009 (hdu 5335)

Problem Description In an n∗m maze, the right-bottom corner is the exit (position (n,m) is the exit). In every position of this maze, there is either a 0 or a 1 written on it. An explorer gets lost in this grid. His position now is (1,1), and he want

2015 多校赛 第五场 1009 (hdu 5348)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题目大意:给出一幅无向图,问是否存在一种方案,使得给每条边赋予方向后,每个点的入度与出度之差小于等于1.如不存在,输出-1:存在,则按边的输入顺序输出方向. 比如:若给出第 m 条边为 u,v,则在对应第m行输出0表示u->v,输出1表示u<-v. 解题思路: 首先证明一定可以构造出符合要求的图. 对于一个环,显然可以使得其内的每个点入度与出度相等.之后可以把环看成点. 对于一棵树,则可以通

2015 多校赛 第七场 1011 (hdu 5379)

题意:给定一棵树,树上有 n 个节点.问有多少种方案,使得在每个节点上依次放置数 1~n 后,每个节点的儿子节点上的数连续(比如 1 为根,有1-2,1-3,1-4,则令2,3,4上的数连续),每个子树上的数连续. 注释在代码里. #pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<algorithm> #

hdu5336 多校联合第四场1010 模拟+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 "siz

hdu 5328 Problem Killer(杭电多校赛第四场)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5328 题目大意:找到连续的最长的等差数列or等比数列. 解题思路:1.等差等比的性质有很多.其中比较重要的一个就是解题关键:如a[i-2],a[i-1],a[i],a[i+1]这个序列.a[i-2],a[i-1],a[i]是等差数列,a[i-1],a[i],a[i+1]也是等差数列.那么a[i-2],a[i-1],a[i],a[i+1]就是等差数列.  2. 等比数列也是一样的~~只要根据这个性质就

HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作. 线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作, 进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明

【杂题总汇】HDU多校赛第十场 Videos

[HDU2018多校赛第十场]Videos 最后一场比赛也结束了-- +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和看了这部电影会得到的快乐值.电影分成两种类型,若同一个人连续(不是时间连续,是顺序连续)看了两部相同类型的电影,他的快乐值会扣除W,数据保证扣除的值不超过电影增加的快乐值. 特别的,一个人换电影不花费时间,即若第一部电影的结束时间等于下一部电影的开始时间,是可以两场都看的:看电影必须看完:一部电影只能一个人看

HDU多校赛第9场 HDU 4965Fast Matrix Calculation【矩阵运算+数学小知识】

难度上,,,确实,,,不算难 问题是有个矩阵运算的优化 题目是说给个N*K的矩阵A给个K*N的矩阵B(1<=N<=1000 && 1=<K<=6),先把他们乘起来乘为C矩阵,然后算C^(N*N) 相当于 ABABABABABABAB...=(AB)^(N*N) 不如 A(BA)^(N*N-1)B 因为BA乘得K*K的矩阵,K是比较小的 #include <cstdio> #include <cstdlib> #include <cstr