http://www.lydsy.com/JudgeOnline/problem.php?id=1033

经半个下午+一个晚上+半个晚上 的 昏天黑地调代码

最终成果:

codevs、洛谷、tyvj上AC

COGS数据本机评测AC,提交50

bzoj WA

1、新产生蚂蚁时,如果洞口有蚂蚁,则不产生

2、移动的时候,第一次不能动,就不能动,接着下一次还不能动,那就可以走回之前来的那个位置

3、攻击,炮选定目标蚂蚁之后,要判断被殃及的蚂蚁所在圆是否与激光(线段)有交点

判断方式:

先判断是否与激光那条直线L有交点,没有交点则不会殃及

如果有交点,

求出 与L 垂直,且过 被殃及蚂蚁 圆心 的直线 LI

那么 L与LI 的交点 即为 垂足

若垂足 在 激光(线段)上(垂足横坐标在 线段两端点之间),则会殃及

若 线段两端点中的一个 与可能被殃及蚂蚁 之间的距离<=0.5,蚂蚁也会被殃及

注意还要判断是否在炮的射程内

#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm> using namespace std; const double eps=1e-; int N,M;
int S,D,R;
int T; struct TURRET
{
int x,y;
}Turret[]; struct ANT
{
int x,y;
int prex,prey;
int level,tim,old;
long long blood;
bool cake;
bool operator < (ANT p) const
{
return old>p.old;
}
}A; vector<ANT>Ant;
vector<ANT>::iterator it; int Ant_sum,size; int sum[][]; int map[][]; // 1 turret ,2 ant,3 cake int dx[]={,,,-};
int dy[]={,,-,}; int Cake_ant=-; int BeHit[]; double BLOOD[]; bool Cake_Left; int cut[],cnt; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void NewAnt()
{
if(size>= || map[][]) return;
Ant_sum++;
A.prex=A.prey=-;
A.blood=*BLOOD[Ant_sum];
A.level=(Ant_sum-)/+;
Ant.push_back(A);
size++;
map[][]=;
} void LeavePheromone()
{
for(int i=;i<size;++i)
{
if(Ant[i].blood<) continue;
if(Ant[i].cake) sum[Ant[i].x][Ant[i].y]+=;
else sum[Ant[i].x][Ant[i].y]+=;
}
} bool inmap(int x,int y)
{
if(x< || x>N || y< || y>M) return false;
if(map[x][y]) return false;
return true;
} void AntMove()
{
int aimx,aimy,aimd,mx;
int nx,ny,nd;
int tmpx,tmpy; for(int i=;i<size;++i)
{
mx=-;
Ant[i].tim++;
aimx=aimy=tmpx=tmpy=-;
for(int j=;j<;++j)
{
nx=Ant[i].x+dx[j];
ny=Ant[i].y+dy[j];
if(inmap(nx,ny))
{
if(sum[nx][ny]>mx)
{
if(Ant[i].prex==nx && Ant[i].prey==ny)
{
tmpx=nx;
tmpy=ny;
continue;
}
mx=sum[nx][ny];
aimx=nx;
aimy=ny;
aimd=j;
}
}
}
bool flag=true;
if(aimx==- && aimy==-)
{
if(Ant[i].prex==Ant[i].x && Ant[i].prey==Ant[i].y && tmpx!=-)
{
aimx=tmpx;
aimy=tmpy;
flag=false;
}
else
{
Ant[i].prex=Ant[i].x;
Ant[i].prey=Ant[i].y;
if(Ant[i].x==N && Ant[i].y==M && Cake_Left)
{
Ant[i].cake=true;
long long first=*BLOOD[*(Ant[i].level-)+];
Ant[i].blood=min(Ant[i].blood+first/,first);
Cake_Left=false;
Cake_ant=i;
}
continue;
}
}
if(!(Ant[i].tim%) && flag)
{
if(aimd==) aimy--;
else if(aimd==) aimx--;
else if(aimd==) aimy++;
else aimx++;
nd=aimd;
while()
{
nd--;
if(nd<) nd=;
nx=aimx+dx[nd];
ny=aimy+dy[nd];
if(inmap(nx,ny))
{
if(Ant[i].prex==nx && Ant[i].prey==ny) continue;
aimx=nx;
aimy=ny;
break;
}
}
}
map[Ant[i].x][Ant[i].y]=;
Ant[i].prex=Ant[i].x;
Ant[i].prey=Ant[i].y;
Ant[i].x=aimx;
Ant[i].y=aimy;
map[aimx][aimy]=;
if(aimx==N && aimy==M && Cake_Left)
{
Ant[i].cake=true;
long long first=*BLOOD[*(Ant[i].level-)+];
Ant[i].blood=min(Ant[i].blood+first/,first);
Cake_Left=false;
Cake_ant=i;
}
}
} double PointPointDis(int xa,int ya,int xb,int yb)
{
return sqrt(1.0*(xa-xb)*(xa-xb)+(ya-yb)*(ya-yb));
} double PointLineDis(int x,int y,double A,double B,double C)
{
return abs(A*x+B*y+C)/sqrt(A*A+B*B);
} bool dcmp(double x,double y)
{
if(fabs(x-y)<eps) return true;
return x<y;
} void Attack(int t)
{
double A,C,nA,nC;
int Aim_ant;
double mi,dis;
double Interx;
bool ok;
memset(BeHit,,sizeof(BeHit));
for(int i=;i<=S;++i)
{
Aim_ant=-;
if(Cake_ant!=- && dcmp(PointPointDis(Turret[i].x,Turret[i].y,Ant[Cake_ant].x,Ant[Cake_ant].y),R))
{
Aim_ant=Cake_ant;
}
else
{
mi=;
for(int j=;j<size;++j)
{
dis=PointPointDis(Turret[i].x,Turret[i].y,Ant[j].x,Ant[j].y);
if(dis<mi && dcmp(dis,R))
{
mi=dis;
Aim_ant=j;
}
}
}
if(Aim_ant==-) continue;
if(abs(Ant[Aim_ant].x-Turret[i].x)<1e-)
{
for(int j=;j<size;++j)
{
if(dcmp(abs(Ant[j].x-Ant[Aim_ant].x),0.5) && dcmp(Ant[j].y-0.5,max(Ant[Aim_ant].y,Turret[i].y)) && dcmp(min(Ant[Aim_ant].y,Turret[i].y),Ant[j].y+0.5))
{
// if(t==T) printf("%d %d %d %d %d %d %d\n",i,Aim_ant,j,Ant[Aim_ant].x,Ant[Aim_ant].y,Ant[j].x,Ant[j].y);
BeHit[j]++;
}
}
}
else if(abs(Ant[Aim_ant].y-Turret[i].y)<eps)
{
for(int j=;j<size;++j)
{
if(dcmp(abs(Ant[j].y-Ant[Aim_ant].y),0.5) && dcmp(Ant[j].x-0.5,max(Ant[Aim_ant].x,Turret[i].x)) && dcmp(min(Ant[Aim_ant].x,Turret[i].x),Ant[j].x+0.5))
{
//if(t==T) printf("%d %d %d %d %d %d %d\n",i,Aim_ant,j,Ant[Aim_ant].x,Ant[Aim_ant].y,Ant[j].x,Ant[j].y);
BeHit[j]++;
}
}
}
else
{
A=1.0*(Ant[Aim_ant].y-Turret[i].y)/(Ant[Aim_ant].x-Turret[i].x);
C=Turret[i].y-A*Turret[i].x;
for(int j=;j<size;++j)
{
if(j==Aim_ant) { BeHit[j]++; continue; }
if(!dcmp(PointPointDis(Turret[i].x,Turret[i].y,Ant[j].x,Ant[j].y),R)) continue;
ok=false;
if(dcmp(PointLineDis(Ant[j].x,Ant[j].y,A,-,C),0.5))
{
nA=-1.0/A; nC=Ant[j].y-nA*Ant[j].x;;
Interx=(nC-C)/(A-nA);
if(Interx>min(Ant[Aim_ant].x,Turret[i].x) && Interx<max(Ant[Aim_ant].x,Turret[i].x)) ok=true;
else
{
if(dcmp(PointPointDis(Turret[i].x,Turret[i].y,Ant[j].x,Ant[j].y),0.5) || dcmp(PointPointDis(Ant[Aim_ant].x,Ant[Aim_ant].y,Ant[j].x,Ant[j].y),0.5)) ok=true;
}
}
if(ok)
{
//if(t==T) printf("%d %d %d %d %d %d %d\n",i,Aim_ant,j,Ant[Aim_ant].x,Ant[Aim_ant].y,Ant[j].x,Ant[j].y);
BeHit[j]++;
}
}
}
}
cnt=;
/* if(t==T)
{
for(int i=0;i<size;++i) printf("%d %d %I64d %d %d\n",Ant[i].old,Ant[i].level,Ant[i].blood,Ant[i].x,Ant[i].y);
}*/
for(int i=;i<size;++i)
{
Ant[i].blood-=1LL*BeHit[i]*D;
if(Ant[i].blood<)
{
map[Ant[i].x][Ant[i].y]=;
cut[++cnt]=i;
if(Cake_ant!=- && Ant[Cake_ant].blood<)
{
Cake_Left=true;
Cake_ant=-;
}
}
}
int k;
for(int i=;i<=cnt;++i)
{
for(it=Ant.begin(),k=;k<cut[i];++k,++it);
Ant.erase(it);
for(int j=i+;j<=cnt;++j) cut[j]--;
if(Cake_ant>cut[i]) Cake_ant--;
}
size-=cnt;
} bool GameOver()
{
if(Cake_ant==-) return false;
if(Ant[Cake_ant].x || Ant[Cake_ant].y) return false;
return true;
} void End()
{
for(int i=;i<=N;++i)
for(int j=;j<=M;++j) if(sum[i][j]) sum[i][j]--;
for(int i=;i<size;++i)
if(Ant[i].blood>=) Ant[i].old++;
} void Print()
{
printf("%d\n",size);
sort(Ant.begin(),Ant.end());
for(int i=;i<size;++i) printf("%d %d %lld %d %d\n",Ant[i].old,Ant[i].level,Ant[i].blood,Ant[i].x,Ant[i].y);
} int main()
{
//freopen("antbuster_ex.in","r",stdin);
//freopen("antbuster_ex.out","w",stdout);
read(N); read(M);
read(S); read(D); read(R);
for(int i=;i<=S;++i)
{
read(Turret[i].x),read(Turret[i].y);
map[Turret[i].x][Turret[i].y]=;
}
Cake_Left=true;
read(T);
double tmp=;
for(int i=;i<=T;i+=)
{
tmp*=1.1;
for(int j=i;j<min(i+,T+);++j) BLOOD[j]=tmp;
}
for(int i=;i<=T;++i)
{
NewAnt();
LeavePheromone();
AntMove();
Attack(i); if(GameOver())
{
printf("Game over after %d seconds\n",i);
Print();
return ;
}
End();
}
puts("The game is going on");
Print();
}

2048. [ZJOI 2008] 杀蚂蚁 (完整版)

★★★★   输入文件:antbuster_ex.in   输出文件:antbuster_ex.out   简单对比
时间限制:3 s   内存限制:128 MB

【题目描述】

最近,佳佳迷上了一款好玩的小游戏:antbuster。游戏规则非常简单:在一张地图上,左上角是蚂蚁窝,右下角是蛋糕,蚂蚁会源源不断地从窝里爬出来,试图把蛋糕搬回蚂蚁窝。而你的任务,就是用原始资金以及杀蚂蚁获得的奖金造防御塔,杀掉这些试图跟你抢蛋糕的蚂蚁~ 下附一张游戏截图:

为了拿到尽可能高的分数,佳佳设计了很多种造塔的方案,但在尝试了其中的一小部分后,佳佳发现,这个游戏实在是太费时间了。为了节省时间,佳佳决定写个程序,对于每一种方案,模拟游戏进程,根据效果来判断方案的优劣。根据自己在游戏中积累的一些经验,以及上网搜到的一些参数,佳佳猜了蚂蚁爬行的算法

并且假设游戏中的蚂蚁也是按这个规则选择路线:

1、每一秒钟开始的时候,蚂蚁都在平面中的某个整点上。如果蚂蚁没有扛着蛋糕,它会在该点留下2单位的信息素,否则它会留下5单位的信息素。然后蚂蚁会在正北、正南、正东、正西四个方向中选择一个爬过去。

2、选择方向的规则是:首先,爬完一个单位长度后到达的那个点上,不能有其他蚂蚁或是防御塔,并且那个点不能是蚂蚁上一秒所在的点(除非上一个时刻蚂蚁就被卡住,且这个时刻它仍无法动),当然,蚂蚁也不会爬出地图的边界(我们定义这些点为不可达点)。如果此时有多个选择,蚂蚁会选择信息素最多的那个点爬过去。

3、如果此时仍有多种选择,蚂蚁先面向正东,如果正东不是可选择的某个方向,它会顺时针转90°,再次判断,如果还不是,再转90°...直到找到可以去的方向。

4、如果将每只蚂蚁在洞口出现的时间作为它的活动时间的第1秒,那么每当这只蚂蚁的活动时间秒数为5的倍数的时候,它先按规则1~3确定一个方向,面对该方向后逆时针转90°,若它沿当前方向会走到一个不可达点,它会不停地每次逆时针转90°,直到它面对着一个可达的点,这样定下的方向才是蚂蚁最终要爬去的方向。

5、如果蚂蚁的四周都是不可达点,那么蚂蚁在这一秒内会选择停留在当前点。下一秒判断移动方向时,它上一秒所在点为其当前停留的点。

6、你可以认为蚂蚁在选定方向后,瞬间移动到它的目标点,这一秒钟剩下的时间里,它就停留在目标点。

7、蚂蚁按出生的顺序移动,出生得比较早的蚂蚁先移动。

然后,是一些有关地图的信息:

1、 每一秒,地图所有点上的信息素会损失1单位,如果那个点上有信息素的话。

2、 地图上某些地方是炮台。炮台的坐标在输入中给出。

3、 地图的长、宽在输入中给出,对于n * m的地图,它的左上角坐标为(0,0),右下角坐标为(n,m)。蚂蚁洞的位置为(0,0),蛋糕的位置为(n,m)。

4、 你可以把蚂蚁看做一个直径为1单位的圆,圆心位于蚂蚁所在的整点。

5、 游戏开始时,地图上没有蚂蚁,每个点上的信息素含量均为0。

一些有关炮塔的信息:

1、 炮塔被放置在地图上的整点处。

2、 为了简单一些,我们认为这些炮塔都是激光塔。激光塔的射速是1秒/次,它的攻击伤害为d/次,攻击范围为r。你可以认为每秒蚂蚁移动完毕后,塔才开始攻击。并且,只有当代表蚂蚁的圆的圆心与塔的直线距离不超过r时,塔才算打得到那只蚂蚁。

3、 如果一只蚂蚁扛着蛋糕,那么它会成为target,也就是说,任何打得到它的塔的炮口都会对准它。如果蛋糕好好地呆在原位,那么每个塔都会挑离它最近的蚂蚁进行攻击,如果有多只蚂蚁,它会选出生较早的一只。

4、 激光塔有个比较奇怪的特性:它在选定了打击目标后,只要目标在其射程内,塔到目标蚂蚁圆心的连线上的所有蚂蚁(这里“被打到”的判定变成了表示激光的线段与表示蚂蚁的圆有公共点)都会被打到并损d格血,但激光不会穿透它的打击目标打到后面的蚂蚁。

5、 尽管在真实游戏中,塔是可以升级的,但在这里我们认为塔的布局和等级就此定了下来,不再变动。

再介绍一下蚂蚁窝:

1、 如果地图上的蚂蚁不足6只,并且洞口没有蚂蚁,那么窝中每秒会爬出一只蚂蚁,直到地图上的蚂蚁数为6只。

2、 刚出生的蚂蚁站在洞口。

3、 每只蚂蚁有一个级别,级别决定了蚂蚁的血量,级别为k的蚂蚁的血量为int(4*1.1^k)(int(x)表示对x取下整)。每被塔打一次,蚂蚁的血减少d。注意,血量为0的蚂蚁仍能精力充沛地四处乱爬,只有一只蚂蚁的血被打成负数时,它才算挂了。

4、 蚂蚁的级别是这样算的:前6只出生的蚂蚁是1级,第7~12只是2级,依此类推。

最后给出关于蛋糕的介绍:

1、 简单起见,你可以认为此时只剩最后一块蛋糕了。如果有蚂蚁走到蛋糕的位置,并且此时蛋糕没有被扛走,那么这只蚂蚁就扛上了蛋糕。蚂蚁被打死后蛋糕归位。

2、 如果一只扛着蛋糕的蚂蚁走到蚂蚁窝的位置,我们就认为蚂蚁成功抢到了蛋糕,游戏结束。

3、 蚂蚁扛上蛋糕时,血量会增加int(该蚂蚁出生时血量 / 2),但不会超过上限。

整理一下1秒钟内发生的事件: 1秒的最初,如果地图上蚂蚁数不足6,一只蚂蚁就会在洞口出生。接着,蚂蚁们在自己所在点留下一些信息素后,考虑移动。先出生的蚂蚁先移动。移动完毕后,如果有蚂蚁在蛋糕的位置上并且蛋糕没被拿走,它把蛋糕扛上,血量增加,并在这时被所有塔设成target。然后所有塔同时开始攻击。如果攻击结束后那只扛着蛋糕的蚂蚁挂了,蛋糕瞬间归位。攻击结束后,如果发现扛蛋糕的蚂蚁没死并在窝的位置,就认为蚂蚁抢到了蛋糕。游戏也在此时结束。最后,地图上所有点的信息素损失1单位。所有蚂蚁的年龄加1。漫长的1秒到此结束。

【输入格式】

输入的第一行是2个用空格隔开的整数,n、m,分别表示了地图的长和宽。第二行是3个用空格隔开的整数,s、d、r,依次表示炮塔的个数、单次攻击伤害以及攻击范围。接下来s行,每行是2个用空格隔开的整数x、y,描述了一个炮塔的位置。当然,蚂蚁窝的洞口以及蛋糕所在的位置上一定没有炮塔。最后一行是一个正整数t,表示我们模拟游戏的前t秒钟。

【输出格式】

如果在第t秒或之前蚂蚁抢到了蛋糕,输出一行“Game over after x seconds”,其中x为游戏结束的时间,否则输出“The game is going on”。如果游戏在t秒或之前结束,输出游戏结束时所有蚂蚁的信息,否则输出t秒后所有蚂蚁的信息。格式如下:第一行是1个整数s,表示此时活着的蚂蚁的总数。接下来s行,每行5个整数,依次表示一只蚂蚁的年龄(单位为秒)、等级、当前血量,以及在地图上的位置(a,b)。输出按蚂蚁的年龄递减排序。

【样例输入】

8 8

2 10 1

7 8

8 6

5

【样例输出】

The game is going on

5

5 1 4 1 4

4 1 4 0 4

3 1 4 0 3

2 1 4 0 2

1 1 4 0 1

最新文章

  1. 【leetcode】Add Two Numbers
  2. underscore源码解析 (转载)
  3. Node.js学习记录
  4. 结合使用saiku、mondrian workbentch建立多维查询报表
  5. 从Uboot到Linux技术内幕
  6. [html][转]常用返回顶部代码
  7. Google maps API开发(一)(转)
  8. 如何让低版本的IE浏览器(IE6/IE7/IE8)支持HTML5 header等新标签
  9. poj 3045 Cow Acrobats(二分搜索?)
  10. poj3667(线段树)
  11. 网络AFNetworking 3.1
  12. js保留两位小数数字
  13. 死磕 java集合之ConcurrentLinkedQueue源码分析
  14. 为什么做java开发的公司需要那么多程序员?
  15. Linux之磁盘分区
  16. pycharm License server激活
  17. JPA使用指南 javax.persistence的注解配置讲解
  18. SpringBoot扩展SpringMVC自动配置
  19. 存储过程+Jquery+WebService实现三级联动:
  20. php 测试 程序执行时间,内存使用情况

热门文章

  1. Beta Scrum Day 3 — 听说
  2. Leetcode题库——24.两两交换链表中的节点
  3. POJ 3597 Polygon Division 多边形剖分
  4. sql经常出现死锁解决办法
  5. angularJS1笔记-(16)-模块里的constant、value、run
  6. Redis有序集内部实现原理分析
  7. ABP ModuleZero后台框架materialize禁止模拟select和checkbox
  8. Scrum 项目准备5.0
  9. 2013成都网赛1010 hdu 4737 A Bit Fun
  10. android之layer-list