传送门

快乐模拟,修身养性

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

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

注意仔细读题,蚂蚁每 $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. C# 指定索引排序 (原)

    private void test(string[] sortkey_list, string[] list_temp) { //打开excel到dt: " }; string[] roww ...

  2. NOIP2018 D1T3赛道修建

    题目链接:Click here Solution: 最小值最大,考虑二分一个答案\(k\) 考虑在子树内先匹配,最后传递一个值给自己的父亲(因为每条边只能用一次,所以一颗子树最多传递一个值) 那么我们 ...

  3. js控制手机保持亮屏的库,解决h5移动端,自动息屏问题

    一些说明:我用Laya(ts)开发小游戏,有需要保持手机屏幕常亮的需求(非必须的),然后作为小白的我就在网上找到了这个库,大概了解下,应该是通过播放空视频的原理来保持手机屏幕常亮,然后就放到项目中试了 ...

  4. [CSP-S模拟测试]:Walker(数学)

    题目传送门(内部题86) 输入格式 第一行$n$接下来$n$行,每行四个浮点数,分别表示变换前的坐标和变换后的坐标 输出格式 第一行浮点数$\theta$以弧度制表示第二行浮点数$scale$第三行两 ...

  5. 关于MySQL去除查询结果重复值

    下面先来看看例子: table:  id name  1 a  2 b  3 c  4 c  5 b 库结构大概这样,这只是一个简单的例子,实际情况会复杂得多. 比如我想用一条语句查询得到name不重 ...

  6. 2018年5月6日GDCPC(广东赛区)总结

    大二第二次参加省赛了,这次成绩不是太理想. ———————————————————————————————— day1:试机 约好的12点钟在地铁站集合,好像就我一个人迟到了5分钟,被sen主席批判一 ...

  7. (C++C#类型互转工具)使用Signature Tool自动生成P/Invoke调用Windows API的C#函数声明

    在网上看到很多网友在.NET程序中调用Win32 API,或者调用自己的VC DLL里面提供的函数的时候,总是被生成正确的C函数在C#中的正确声明而困扰,而生成C++中结构体在C#中的声明 - 天,没 ...

  8. vs2019安装

    1.下载vs_enterprise.exe(建议下载到无中文无空格目录) ,这个很小,官网下载企业版即可 2.在当前目录cmd命令执行: vs_enterprise.exe --layout offl ...

  9. HAProxy & Keepalived L4-L7 高可用负载均衡解决方案

    目录 文章目录 目录 HAProxy 负载均衡器 应用特性 性能优势 会话保持 健康检查 配置文件 负载均衡策略 ACL 规则 Web 监控平台 Keepalived 虚拟路由器 核心组件 VRRP ...

  10. Failed building wheel for netifaces

    目录 文章目录 目录 问题 解决 问题 安装 OpenStackClient 的时候发现问题: Failed building wheel for netifaces Running setup.py ...