hdu 5336 XYZ and Drops 2015 Multi-University Training Contest 4

模拟题卡到了现在><简直被自己蠢哭了。

直接用BFS模拟drop的运动状态。只有waterdrop meets drop才会合并,两个drop meet不会合并。且合并后waterdrop不会再运动,所以如果发生了合并,next节点不需再入队。

坑在了一个地方就是需要避免同一个位置crack多次的case,考虑一下这种case:

04A

0B0

其中4表示有一个size=4的waterdrop,坐标为(1,2);0表示空。在t时刻A、B处各有一个drop在向waterdrop运动。扩展B时,队列中会加入(1,2) size=5的节点C,之后再扩展A时,队列中会加入(1,2) size=6的节点D。那么t+1时刻C、D出队,(1,2)这一处就被crack了两次。避免这种case的方法,第一种是仅将合并后size==5时将next节点入队,size==5是第一次达到crack的标准。这样就避免了扩展多次重复的可以crack的节点。另一种是对每个入队的节点设一个bool Crack,如果出队的某个节点Crack==true而对应的mp[x][y]==0,就说明该位置之前已经cracked了,就可以忽略此次crack。

另外BFS返回时不能在time==T就return,需要continue,并且return前需要判断该节点会不会在T时刻crack。因为可能有多个节点会在T时刻crack,所以需要判断完所有的time==T的node。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<ctype.h>
#include<map>
#include<time.h>
#include<bitset>
#include<set>
#include<list>
using namespace std;
//hdu 5336

const int maxn=110;
int T;
int r;
int c;
int n;
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
class node
{
public:
    int x;
    int y;
    int dis;
    int dir;
    int idx;
    bool crack;
public:
    node()
    {
        x=0;
        y=0;
        dis=0;
        dir=0;
        idx=0;
        crack=false;
    }
};
node point[maxn];
int mp[maxn][maxn];
int subidx[maxn][maxn];
int mark[maxn];
int tim[maxn][maxn];
node st;
pair<int,int>ans[maxn];
void bfs()
{
    queue<node>que;
    node now=node();
    st.dis=0;
    st.idx=subidx[st.x][st.y];
    st.crack=true;
    que.push(st);
    mp[st.x][st.y]=5;
    while(!que.empty())
    {
        now=que.front();
        que.pop();
        if(now.dis==T) //the node "now" may be cracked at time T
        {
//            ans[now.idx]=make_pair(1,mp[now.x][now.y]);
//            mark[now.idx]=true;

            if(mp[now.x][now.y]>4)
            {
                tim[now.x][now.y]=now.dis;
                mp[now.x][now.y]=0;
                ans[now.idx]=make_pair(0,now.dis);
                mark[now.idx]=true;
            }
           // return;
            continue; //there could be more than one drop cracking at time T
        }
        //if(now.crack==true) //it's also ok then push the node into the queue only when mp[x0][y0]==5;
        if(mp[now.x][now.y]>4)
        {
            if(subidx[now.x][now.y]!=0)//exclude the start point if it's not a drop
            {
                ans[now.idx]=make_pair(0,now.dis);
                mark[now.idx]=true;
            }
            tim[now.x][now.y]=now.dis;
            mp[now.x][now.y]=0;//crack
            for(int i=0;i<4;i++)
            {
                int x0=now.x+dx[i];
                int y0=now.y+dy[i];
                if(x0<1||x0>r||y0<1||y0>c) continue;//||now.dis==T if there is no "continue" before, we need to add this condition or ||now.dis>=T
                node next=node();
                next.dis=now.dis+1;
                next.x=x0;
                next.y=y0;
                next.dir=i;
                next.idx=subidx[x0][y0];
                next.crack=false;
                if(mp[x0][y0])
                {
                    mp[x0][y0]++;
                    if(mp[x0][y0]>4)
                    {
                        next.crack=true;
                        que.push(next);
                    }
                }
                else
                {
                    que.push(next);
                }
            }
        }
        else
        {
            if(now.crack==true)
            {
                continue;
            }
            int x0=now.x+dx[now.dir];
            int y0=now.y+dy[now.dir];
            if(x0<1||x0>r||y0<1||y0>c) continue;//||now.dis==T
            node next=node();
            next.dis=now.dis+1;
            next.x=x0;
            next.y=y0;
            next.dir=now.dir;
            next.idx=subidx[x0][y0];
            next.crack=false;
            if(mp[x0][y0])
            {
                mp[x0][y0]++;
                if(mp[x0][y0]>4)
                {
                    next.crack=true;
                    que.push(next);
                }
            }
            else
            {
                que.push(next);
            }
        }
    }
}
int main()
{
    freopen("input.txt","r",stdin);
    while(scanf("%d %d %d %d",&r,&c,&n,&T)!=EOF)
    {
        memset(mp,0,sizeof(mp));
        memset(subidx,0,sizeof(subidx));
        memset(point,0,sizeof(point));
        memset(mark,false,sizeof(mark));
        memset(ans,0,sizeof(ans));
        memset(tim,0,sizeof(tim));
        for(int i=1;i<=n;i++)
        {
            int x=0;
            int y=0;
            int sz=0;
            scanf("%d %d %d",&x,&y,&sz);
            point[i].x=x;
            point[i].y=y;
            mp[x][y]=sz;
            point[i].idx=i;
            subidx[x][y]=i;
        }
        scanf("%d %d",&st.x,&st.y);
        bfs();
        for(int i=1;i<=n;i++)
        {
//            if(mp[point[i].x][point[i].y])
//            {
//                printf("1 %d\n",mp[point[i].x][point[i].y]);
//            }
//            else
//            {
//                printf("0 %d\n",tim[point[i].x][point[i].y]);
//            }
            if(mark[i]==true)
            {
                printf("%d %d\n",ans[i].first,ans[i].second);
            }
            else
            {
                printf("1 %d\n",mp[point[i].x][point[i].y]);
            }
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值