传送门

快乐模拟,修身养性

代码长度其实还好,主要是细节多

只要知道一些计算几何基础知识即可快乐模拟,按着题目要求一步步实现就行啦

注意仔细读题,蚂蚁每 $5$ 秒乱走一次的时候是只要能走就走了,不一定要信息素最多

还有因为炮台是同时打的,所以目标要提前选好,就算某只蚂蚁被打成负血了,还是会继续被打

蚂蚁初始年龄为 $0$,活动时间是按 $1$ 开始的(看样例就懂了)

我用 $set$ 按年龄维护蚂蚁信息,注意枚举 $set$ 内的蚂蚁时要先把 $set$ 的信息统一取出,不然可能会指针越界

把取出后修改的信息再重新放回 $set$ 即可,具体模拟实现当然还是看代码啦,当然最好还是自己写一遍,$std$ 拿来对拍比较好

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
typedef double db;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const db eps=1e-;
const int N=,xx[]={,,,-},yy[]={,,-,};
inline int dcmp(db x) { if(fabs(x)<eps) return ; return x< ? - : ; }
int n,m,S,attack,R,T,ant_cnt;
//矩阵长宽,炮台数量,攻击,半径,时间,目前蚂蚁数量
int Map[N][N],Vis[N][N];
//维护地图信息素,维护地图被占用的位置
bool Cake=,GG;//是否有蛋糕,游戏是否结束
struct Point {
int x,y;
Point (int a=,int b=) { x=a,y=b; }
inline bool operator == (const Point &tmp) const { return x==tmp.x&&y==tmp.y; }
inline Point operator - (const Point &tmp) const { return Point(x-tmp.x,y-tmp.y); }
inline Point to(int k) { return Point(x+xx[k],y+yy[k]); }
};
inline db Cross(Point A,Point B) { return A.x*B.y-A.y*B.x; }
inline db Dot(Point A,Point B) { return A.x*B.x+A.y*B.y; }
inline db Len(Point A) { return sqrt(Dot(A,A)); }
//以上计算几何板子
inline bool pd(Point P) { return P.x<||P.x>n||P.y<||P.y>m||Vis[P.x][P.y]; }//判断位置合法性
struct Ant {//蚂蚁信息
int blood,age,mxbld,lev;
//当前血量,年龄,最大生命,等级
bool target; Point P,pre;
//是否有蛋糕,当前位置,上一步的位置
Ant (int c=,int d=,int e=,int f=,bool h=,Point A=Point(,),Point B=Point(,)) {
blood=c,age=d,mxbld=e,lev=f,target=h; P=A; pre=B;
}
void Move()//进行移动
{
int X[],tot=,mx=; Vis[P.x][P.y]=;//原本位置蚂蚁走了
for(int i=;i<;i++)//按方向枚举
{
Point t=P.to(i);
if(pd(t)||t==pre||(tot && Map[t.x][t.y]<mx)) continue;//判断不合法
if(Map[t.x][t.y]>mx) mx=Map[t.x][t.y],tot=;//修改合法方向
X[++tot]=i;
}
if(!tot) { pre=P; Vis[P.x][P.y]=; return; }//判断不可走
if((age+)%) { pre=P; P=P.to(X[]); Vis[P.x][P.y]=; return ; }//正常移动
for(int k=(X[]+)%,i=;i<;i++,k=(k+)%)//5秒乱走一次
{
Point t=P.to(k);
if(!pd(t)&&!(t==pre))//只要可以走就直接走了
{ pre=P,P=t,Vis[P.x][P.y]=; return; }
}
}
void try_to_get_cake()//看看能不能得到蛋糕
{
if(P.x!=n||P.y!=m||!Cake) return;
Cake=; blood=min(mxbld,blood+(mxbld/)); target=;
//得到蛋糕,更新数据
}
inline bool operator < (const Ant &tmp) const { return age>tmp.age; }//按年龄排序
}tmp[N];
int tot;//tmp的右端点
set <Ant> ant;
inline db Dis(Point P,Point Q,Point A)
{
if(dcmp(Dot(A-P,Q-P))<) return Len(A-P);
if(dcmp(Dot(A-Q,P-Q))<) return Len(A-Q);
return fabs(Cross(A-P,Q-P)/Len(Q-P));
}//同样计算几何板子,求A到线段PQ的距离
struct turret {//炮台
Point P;//坐标
void Attack()//进行攻击
{
Ant to,A; db mi=N;
for(int i=;i<=tot;i++)
{
A=tmp[i];
if(Len(P-A.P)>1.0*R+eps) continue;//太远就没得打
if(A.target) { to=A; mi=; break; }//发现有target
if(Len(P-A.P)+eps<mi) to=A,mi=Len(P-A.P);//找到最近的蚂蚁
}
if(int(mi+eps)==N) return;//范围内没有目标
for(int i=;i<=tot;i++)
if(Dis(P,to.P,tmp[i].P)<0.5+eps) tmp[i].blood-=attack;//看看能否波及到其他蚂蚁
}
}Tur[N];
inline db ksm(db x,int y)
{
db res=;
while(y) { if(y&) res=res*x; x=x*x; y>>=; }
return res;
}
int cnt;//总共出现的蚂蚁数量
void Work()
{
if(ant_cnt<&&!Vis[][])//当前位置没有蚂蚁才能刷蚂蚁
{
Ant New_ant; New_ant.lev=cnt/+;
New_ant.blood=New_ant.mxbld=4.0*ksm(1.1,New_ant.lev);
New_ant.P=Point(,); Vis[][]=;
ant_cnt++; cnt++; ant.insert(New_ant);//更新一堆数据
}
for(auto A: ant)//更新地图信息素
{
if(!A.target) Map[A.P.x][A.P.y]+=;
else Map[A.P.x][A.P.y]+=;
}
tot=; for(auto A: ant) tmp[++tot]=A;//取出数据
for(int i=;i<=tot;i++)
{
ant.erase(tmp[i]),tmp[i].Move();
tmp[i].try_to_get_cake();//移动并判断得到蛋糕
}
for(int i=;i<=S;i++) Tur[i].Attack();//炮台攻击
for(int i=;i<=tot;i++)
{
if(tmp[i].blood>=) ant.insert(tmp[i]);//最后统一插回set
else { ant_cnt--; Vis[tmp[i].P.x][tmp[i].P.y]=; if(tmp[i].target) Cake=; }
//蚂蚁死了,更新数据,归还蛋糕
}
for(auto A: ant) if(A.target&&!A.P.x&&!A.P.y) { GG=; return; }//判断游戏结束
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) if(Map[i][j]) Map[i][j]--;//更新信息素
tot=; for(auto A: ant) tmp[++tot]=A;
for(int i=;i<=tot;i++) ant.erase(tmp[i]),tmp[i].age++;//统一年龄加1
for(int i=;i<=tot;i++) ant.insert(tmp[i]);
}
int main()
{
n=read(),m=read(); S=read(),attack=read(),R=read();
for(int i=;i<=S;i++)
{
Tur[i].P.x=read(),Tur[i].P.y=read();
Vis[ Tur[i].P.x ][ Tur[i].P.y ]=;//炮台不能走
}
int Time=read();
for(int t=;t<=Time;t++)
{
Work();
if(GG) { printf("Game over after %d seconds\n",t); break; }
}
if(!GG) printf("The game is going on\n");
printf("%d\n",int(ant.size()));
for(auto A: ant) printf("%d %d %d %d %d\n",A.age,A.lev,A.blood,A.P.x,A.P.y);
return ;
}

P2586 [ZJOI2008]杀蚂蚁的更多相关文章

  1. P2586 [ZJOI2008]杀蚂蚁(模拟)

    P2586 [ZJOI2008]杀蚂蚁 大模拟. 什么都不想补了. 看变量名感性理解吧 #include<iostream> #include<cstdio> #include ...

  2. Luogu2586 [ZJOI2008]杀蚂蚁 ---- 模拟

    Luogu2586 [ZJOI2008]杀蚂蚁 题意 还是一道大模拟 https://www.luogu.org/problemnew/show/P2586 大概就是炮塔大蚂蚁的故事 下载这个游戏ht ...

  3. [BZOJ 1033][ZJOI2008]杀蚂蚁antbuster

    1033: [ZJOI2008]杀蚂蚁antbuster Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1200  Solved: 507[Submi ...

  4. [ZJOI2008]杀蚂蚁antbuster

    [ZJOI2008]杀蚂蚁antbuster 题目 最近,佳佳迷上了一款好玩的小游戏:antbuster.游戏规则非常简单:在一张地图上,左上角是蚂蚁窝,右下角是蛋糕,蚂蚁会源源不断地从窝里爬出来,试 ...

  5. 【BZOJ 1033】 [ZJOI2008]杀蚂蚁antbuster

    Description 最近,佳佳迷上了一款好玩的小游戏:antbuster.游戏规则非常简单:在一张地图上,左上角是蚂蚁窝,右下角是蛋糕,蚂蚁会源源不断地从窝里爬出来,试图把蛋糕搬回蚂蚁窝.而你的任 ...

  6. bzoj千题计划121:bzoj1033: [ZJOI2008]杀蚂蚁antbuster

    http://www.lydsy.com/JudgeOnline/problem.php?id=1033 经半个下午+一个晚上+半个晚上 的 昏天黑地调代码 最终成果: codevs.洛谷.tyvj上 ...

  7. BZOJ1033:[ZJOI2008]杀蚂蚁antbuster(模拟)

    Description 最近,佳佳迷上了一款好玩的小游戏:antbuster.游戏规则非常简单:在一张地图上,左上角是蚂蚁窝,右 下角是蛋糕,蚂蚁会源源不断地从窝里爬出来,试图把蛋糕搬回蚂蚁窝.而你的 ...

  8. [bzoj1033] [ZJOI2008]杀蚂蚁antbuster

    Description 最近,佳佳迷上了一款好玩的小游戏:antbuster.游戏规则非常简单:在一张地图上,左上角是蚂蚁窝,右下角是蛋糕,蚂蚁会源源不断地从窝里爬出来,试图把蛋糕搬回蚂蚁窝.而你的任 ...

  9. BZOJ1033:[ZJOI2008]杀蚂蚁

    我对模拟的理解:https://www.cnblogs.com/AKMer/p/9064018.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

随机推荐

  1. 开发一个chrome插件:将百度搜索热点屏蔽掉!

    每次百度搜索,搜索结果的右边总是出现些乱七八糟的搜索热点(推的都是些什么玩意,高校替课和我有毛关系,几个悲伤的热点我用星号顶掉了). 强迫症想把它隐藏掉,我用的是chrome浏览器,受adblock( ...

  2. java8中接口default、static新特性,与抽象类区别

    之前Java接口中的方法默认都是public abstract,成员变量默认都是public static final,偶然发现接口中可以有default类型的方法,才知道java8中接口可以有自己的 ...

  3. week4 作业

    week4 作业 1.定义一个对所有用户都生效的命令别名,例如:lftps='lftp 172.168.0.1 /pub' 在 ~/.bashrc中添加命令: alias = 'rm -i' 2.显示 ...

  4. [CSP-S模拟测试]:123567(莫比乌斯函数+杜教筛+数论分块)

    题目传送门(内部题92) 输入格式 一个整数$n$. 输出格式 一个答案$ans$. 样例 样例输入: 样例输出: 数据范围与提示 对于$20\%$的数据,$n\leqslant 10^6$. 对于$ ...

  5. Run nginx from Docker in Windows

    1.首先, 使用 docker run hello-world 命令 确认 docker 在本地安装成功,若成功应如下所示(此处使用的是 Docker Toolbox 在Windows上安装Docke ...

  6. 一款基于jQuery的漂亮弹出层

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  7. SecureCRT通过密钥登录

    转载  https://blog.csdn.net/langkeziju/article/details/53024031 说明:一般的密码方式登录容易被密码暴力破解.所以一般我们会将 SSH 的端口 ...

  8. PM项目跟进护航文档模板

    护航文档 版本需求列表 需求 开发责任人 MMDrawerController.GCDTimer.Speex_armv7s等11个库迁移 熊文杰 相关人员 职称 开发人员 开发 熊文杰 测试 xxx ...

  9. React Router学习笔记(转自阮一峰老师博客)

    React Router是一个路由库,通过管理URL来实现组件切换和状态转变. 1.安装和使用 $ npm install -S react-router 在使用时,作为React组件导入 impor ...

  10. hihoCoder#1879 : Rikka with Triangles (计算几何)

    n<=2000,肯定没有办法把所有三角形找出来全判一遍 对于三角形的三个角,分别计算贡献,锐角的贡献是1倍面积,钝角的贡献是-2倍面积,这样算出角的贡献之后除以3就可以了 每次选择一个点为中心点 ...