【模拟】【计算几何】[ZJOI2008][HYSBZ/BZOJ1033]杀蚂蚁antbuster

题目链接

分析

这道题,是一道十分优(e)秀(xin)的模拟题。
有一些注意事项:

  1. 一边看题一边写,不要把题目读错了
  2. 一切活动都要严格按照这个顺序来,仔细理解题目所给的意思。这是每一秒钟的活动顺序
  3. 注意蚂蚁移动的顺序。
  4. 所有炮塔是同时攻击的。
  5. 这里写图片描述这里写图片描述在模拟中掺杂了计算几何。

知道了这些,写不写得出来,就看你的实(ren)力(pin)了。

代码

#include<cstdio>
#include<algorithm>
#include<set>
#include<iostream>
#include<cmath>
#include<stack>
#define MAXS 20
#define INF 0x7fffffff
#define MAXN 8
using namespace std;
#define MAXT 200000
set<int>se;
int n,m,s,d,r,x[MAXS+10],y[MAXS+10],cnt,b[MAXT+10],t,f[MAXN+10][MAXN+10],cake,num,bt[MAXT+10];
double k1,b1,mypow[MAXT+10];
pair<int,int>pos[MAXT+10],fr[MAXT+10];
int mat[MAXN+10][MAXN+10],dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}},tms;
void Read(int &x){
    char c;
    while(c=getchar(),c!=EOF)
        if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            return;
        }
}
void read(){
    int i;
    Read(n),Read(m),Read(s),Read(d),Read(r);
    for(i=1;i<=s;i++){
        Read(x[i]),Read(y[i]);
        mat[x[i]][y[i]]=-1;
    }
    Read(t);
}
inline int Get_sqdist(int x1,int y1,int x2,int y2){
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
inline double Get_dist(int x1,int y1,int x2,int y2){
    return sqrt(Get_sqdist(x1,y1,x2,y2));
}
void born(){
    if(cnt<6&&!mat[0][0]){
        num++;
        cnt++;
        bt[num]=tms;
        mat[0][0]=num;
        pos[num]=make_pair(0,0);
        b[num]=4*mypow[(num+5)/6];
        se.insert(num);
    }
}
void move(){
    int tx,ty,d,mx,maxdir,ttx,tty,cc;
    set<int>::iterator j;
    for(j=se.begin();j!=se.end();j++){
        tx=pos[*j].first,ty=pos[*j].second;
        f[tx][ty]+=(*j==cake?5:2);
        mx=-1,maxdir=-1,cc=0;
        for(d=0;d<4;d++){
            ttx=tx+dir[d][0],tty=ty+dir[d][1];
            if(ttx>=0&&ttx<=n&&tty>=0&&tty<=m&&!mat[ttx][tty]&&fr[*j]!=make_pair(ttx,tty))
                if(f[ttx][tty]>mx)
                    maxdir=d,mx=f[ttx][tty];
        }
        if(maxdir==-1){
            fr[*j]=pos[*j];
            continue;
        }
        if((tms-bt[*j]+1)%5==0)
            for(maxdir=(maxdir+3)%4;;maxdir=(maxdir+3)%4){
                ttx=tx+dir[maxdir][0],tty=ty+dir[maxdir][1];
                if(ttx>=0&&ttx<=n&&tty>=0&&tty<=m&&!mat[ttx][tty]&&fr[*j]!=make_pair(ttx,tty))
                    break;
            }
        fr[*j]=pos[*j];
        ttx=tx+dir[maxdir][0],tty=ty+dir[maxdir][1];
        mat[tx][ty]=0;
        pos[*j]=make_pair(ttx,tty);
        mat[ttx][tty]=*j;
    }
    if(!cake&&mat[n][m]){
        cake=mat[n][m];
        b[mat[n][m]]=min(b[mat[n][m]]+(int)(4*mypow[(mat[n][m]+5)/6])/2,(int)(4*mypow[(mat[n][m]+5)/6]));
    }
}
double cross_product(int x1,int y1,int x2,int y2){
 return x1*y2-x2*y1;
}
bool cross(int i,int tgt,int num){
    int x1,y1,x2,y2,x3,y3;
    x1=x[i],y1=y[i],x2=pos[tgt].first,y2=pos[tgt].second,x3=pos[num].first,y3=pos[num].second;
    int mnx=min(x1,x2),mxx=max(x1,x2),mny=min(y1,y2),mxy=max(y1,y2);
    if(x3<mnx||x3>mxx||y3<mny||y3>mxy)
        return 0;
    if(fabs(cross_product(x1-x3,y1-y3,x2-x3,y2-y3))<=0.5*Get_dist(x1,y1,x2,y2))
        return 1;
    return 0;
}
void attack(){
    int i,tgt,mi,t;
    set<int>::iterator j;
    for(i=1;i<=s;i++){
        if(cake&&Get_sqdist(x[i],y[i],pos[cake].first,pos[cake].second)<=r*r)
            tgt=cake;
        else{
            tgt=0,mi=r*r+1;
            for(j=se.begin();j!=se.end();j++)
                if((t=Get_sqdist(x[i],y[i],pos[*j].first,pos[*j].second))<mi)
                    tgt=*j,mi=t;
            if(!tgt)
                continue;
        }
        b[tgt]-=d;
        for(j=se.begin();j!=se.end();j++)
            if(*j!=tgt&&cross(i,tgt,*j))
                b[*j]-=d;
    }
}
bool beh_attack(){
    set<int>::iterator j;
    stack<int>ss;
    for(j=se.begin();j!=se.end();j++)
        if(b[*j]<0){
            ss.push(*j);
            mat[pos[*j].first][pos[*j].second]=0;
            cnt--;
        }
    while(!ss.empty()){
        se.erase(ss.top());
        ss.pop();
    }
    if(cake){
        if(b[cake]<0)
            cake=0;
        else if(!pos[cake].first&&!pos[cake].second)
            return 1;
    }
    return 0;
}
void ending(){
    int i,j;
    for(i=0;i<=n;i++)
        for(j=0;j<=m;j++)
            if(f[i][j])
                f[i][j]--;
}
bool solve(){
    for(tms=1;tms<=t;tms++){
        born();
        move();
        attack();
        if(beh_attack())
            return 1;
        ending();
    }
    return 0;
}
void print(){
    printf("%d\n",cnt);
    for(set<int>::iterator j=se.begin();j!=se.end();j++)
        printf("%d %d %d %d %d\n",tms-bt[*j],(*j+5)/6,b[*j],pos[*j].first,pos[*j].second);
}
void prepare(){
    mypow[0]=1;
    for(int i=1;i<=t;i++)
        mypow[i]=mypow[i-1]*1.1;
}
int main()
{
    read();
    prepare();
    if(solve())
        printf("Game over after %d seconds\n",tms);
    else
        puts("The game is going on");
    print();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值