ZOJ 3698 Carrot Fantasy (大模拟)

题意:改编了保卫萝卜的部分功能,给你4个塔和怪物什么的,来模拟是否能够消灭怪物。

解法:比赛的时候一直在敲这题,但是一直wa,结果赛后发现是有数组开小了。。。真是渣渣。。。

由于要考虑怪物的路径,所以用BFS先找出了路径。

之后就是模拟。

总结:太不细心,代码手速太慢。

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
    int x,y;
    int step;
} tower[5][300];  //记录4塔的位置,0-3分别表示三种塔
int pat[20][20],pplen[20][20];
//用来记录路径,pplen记录当前位置到终点的步数,判断攻击的目标时要用。
//pat用来记录路径,当前点的下一个运动方向
int tsum[5],plen;  //tsum 记录相应塔的数量
char map[20][20];
struct monster
{
    int x,y,born,hp;
    bool need,ice;
} mon[60];
//怪物信息,分别表示坐标,born出生的时间,小于0表示还没出生,大于0的才可以动什么的。
//hp血量,need,ice表示是否中毒或者冻住
int m,n,k,h;
int sx,sy,ex,ey,down;  //怪物的起始节点和萝卜的节点
int vis[30][30];
int downhp[60];
bool downice[60];
//由于塔是同时攻击的,所以用这两个数组来记录某次攻击,某个怪物是否要扣血和冻住
//刚开始就由于没看到这个,然后是一个个炮塔去处理,结果wa到死
//最后加了这个之后还是wa,但是数组开小了,赛后才发现,跪。
int pan(char ch)    //判断塔的类型
{
    if(ch=='B') return 0;
    if(ch=='F') return 1;
    if(ch=='N') return 2;
    if(ch=='I') return 3;
    return -1;
}
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int dir1[8][2]= {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
bool inMap(int x,int y)
{
    return (x>=0&&x<m&&y>=0&&y<n);
}
void BFS()
{
    int i,j,x,y,d;
    node temp,newtemp;
    queue<node>q;
    memset(vis,-1,sizeof(vis));
    temp.x=sx,temp.y=sy,temp.step=0;
    vis[sx][sy]=-2;
    q.push(temp);
    while(!q.empty())
    {
        temp=q.front();
        q.pop();
        if(temp.x==ex&&temp.y==ey)
        {
            plen=temp.step;
            x=ex,y=ey;
            while(x!=sx||y!=sy)
            {
                d=vis[x][y];
                pplen[x][y]=temp.step-plen;
                x-=dir[d][0];
                y-=dir[d][1];
                pat[x][y]=d;
                plen--;
            }
            pplen[sx][sy]=temp.step;
            return ;
        }
        for(i=0; i<4; i++)
        {
            newtemp=temp;
            newtemp.x+=dir[i][0];
            newtemp.y+=dir[i][1];
            newtemp.step++;
            if(inMap(newtemp.x,newtemp.y)&&vis[newtemp.x][newtemp.y]==-1
                    &&(map[newtemp.x][newtemp.y]=='.'||map[newtemp.x][newtemp.y]=='T'))
            {
                vis[newtemp.x][newtemp.y]=i;
                q.push(newtemp);
            }
        }
    }
}
int nearest(int x,int y)    //根据题意找攻击对象
{
    int i,j,a,b,mm=-1;
    for(i=0;i<8;i++)
    {
        a=x+dir1[i][0];
        b=y+dir1[i][1];
        if(inMap(a,b))
        {
            for(j=0;j<k;j++)
            {
                if(mon[j].x==a&&mon[j].y==b&&mon[j].hp>0&&mon[j].born>=0)
                {
                    if(mm==-1) mm=j;
                    else
                    {
                        if(pplen[mon[mm].x][mon[mm].y]>pplen[a][b])
                            mm=j;
                        else if(pplen[mon[mm].x][mon[mm].y]==pplen[a][b])
                        {
                            if(mon[mm].born<mon[j].born)
                                mm=j;
                        }
                    }
                }
            }
        }
    }
    return mm;
}
void attack0()      //B
{
    int i,j,a,b,x,y,d;
    for(i=0;i<tsum[0];i++)
    {
        x=tower[0][i].x;
        y=tower[0][i].y;
        d=nearest(x,y);
        if(d!=-1)
        {
            downhp[d]+=10;
            down++;
        }
    }
}
void attack1()      //F
{
    int i,j,a,b,tt,x,y;
    for(i=0;i<tsum[1];i++)
    {
        x=tower[1][i].x;
        y=tower[1][i].y;
        for(j=0;j<8;j++)
        {
            a=x+dir1[j][0];
            b=y+dir1[j][1];
            if(inMap(a,b))
            {
                for(tt=0;tt<k;tt++)
                {
                    if(mon[tt].x==a&&mon[tt].y==b&&mon[tt].born>=0&&mon[tt].hp>0)
                    {
                        downhp[tt]+=10;
                        down++;
                    }
                }
            }
        }
    }
}
void attack2()      //N
{
    int i,j,a,b,x,y,d;
    for(i=0;i<tsum[2];i++)
    {
        x=tower[2][i].x;
        y=tower[2][i].y;
        d=nearest(x,y);
        if(d!=-1)
            mon[d].need=1;
    }
}
void attack3()      //I
{
    int i,j,a,b,x,y,d;
    for(i=0;i<tsum[3];i++)
    {
        x=tower[3][i].x;
        y=tower[3][i].y;
        d=nearest(x,y);
        if(d!=-1)
            downice[d]=1;
    }
}
int main()
{
    int T,i,j,x,minter;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&m,&n,&k,&h);
        for(i=0; i<m; i++) scanf("%s",map[i]);
        memset(tsum,0,sizeof(tsum));
        for(i=0; i<m; i++)
            for(j=0; j<n; j++)
            {
                if(map[i][j]=='S')
                {
                    sx=i;
                    sy=j;
                }
                if(map[i][j]=='T')
                {
                    ex=i;
                    ey=j;
                }
                x=pan(map[i][j]);
                if(x>=0)
                {
                    tower[x][tsum[x]].x=i,tower[x][tsum[x]].y=j;
                    tsum[x]++;
                }
            }
        BFS();
        for(i=0; i<k; i++)
        {
            mon[i].x=sx,mon[i].y=sy;
            mon[i].hp=h;
            mon[i].born=-1*i-1;
            //born初始状态为-1到-k-1,大于0的才可以进行操作
            //这样在每一秒的时候,先对born大于0的进行操作之后再给每个born++
            //就解决了第一秒不能动但是能被攻击的情况
            mon[i].ice=mon[i].need=0;
        }
        bool die=false;

        for(minter=1;; minter++)
        {
            memset(downhp,0,sizeof(downhp));
            memset(downice,0,sizeof(downice));
            down=0;
            for(i=0; i<k; i++)
            {
                if(mon[i].need&&mon[i].hp>0) { mon[i].hp-=10; down++; }
                if(mon[i].born>=0&&mon[i].hp>0)
                {
                    if(mon[i].ice==0)
                    {
                        int xx;
                        xx=pat[mon[i].x][mon[i].y];
                        mon[i].x+=dir[xx][0];
                        mon[i].y+=dir[xx][1];
                        if(mon[i].x==ex&&mon[i].y==ey)
                        {
                            die=1; break;
                        }
                    }
                    else mon[i].ice=0;
                }
                mon[i].born++;
            }
            if(die) break;
            attack0();
            attack1();
            attack2();
            attack3();
            for(i=0;i<k;i++)
            {
                if(downhp[i]) mon[i].hp-=downhp[i];
                if(downice[i]) mon[i].ice=1;
            }
            int ksum=0;
            for(i=0;i<k;i++)
                if(mon[i].hp<=0) ksum++;
            if(ksum==k) break;
            if(down==0&&minter>100) break;
            //判断当所有怪都是被冻住的状态,但是没有能扣血,这样也是不能消灭怪物的,要跳出
            //定义了一个最大的移动步数,本来是2500的,但后来发现减到100也能过,但求证明想法
        }
        if(down==0&&minter>100) printf("-1\n");
        else if(!die) printf("%d\n",minter);
        else printf("-1\n");
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值