【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1033

【题意】



https://www.zybuluo.com/Jerusalem/note/221811

【题解】



。。。

模拟题。

要用到计算几何知识;

即求一段线段是不是和圆相交;

如果一只蚂蚁被打死了.还要一直打才行。

因为有一个蛋糕蚂蚁的判断。。



【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x) typedef pair<int, int> pii;
typedef pair<LL, LL> pll; const int dx[9] = { 0,0,1,0,-1,-1,-1,1,1 };
const int dy[9] = { 0,1,0,-1,0,-1,1,-1,1 };
const double pi = acos(-1.0);
const int MAX_PAOTA = 25;
const int MAX_MAYI = 10;
const int MAX_SIZE = 10; struct point
{
int x, y;
}; struct mayi
{
int x, y, id, xue, cunzai, dangao, prex, prey, age, chushi;
void get_xue(int k)
{
k = ((k - 1) / 6) + 1;//通过id获取它的等级
double t = 1;
rep1(i, 1, k)
t = t*1.1;//计算1.1的k次方
t *= 4;//乘上4
xue = int(t);//转成整数
chushi = xue;//记录初始血量
}
}; int n, m, s, d, r, tot, now, t;//n和m是地图的长和宽
int tu[MAX_SIZE][MAX_SIZE];
//tot是当前出生的蚂蚁的新id
//now是蚂蚁的只数
point paota[MAX_PAOTA];
mayi mayis[MAX_MAYI];
int can[MAX_SIZE][MAX_SIZE];
int get_dangao; bool cmp1(mayi a, mayi b)//按照出生的顺序排
{
return a.id < b.id;
} bool cmp2(mayi a, mayi b)//按年龄递减排
{
return a.age > b.age;
} void in()
{
rei(n), rei(m);
rei(s), rei(d), rei(r);
rep1(i, 1, s)
{
rei(paota[i].x), rei(paota[i].y);
can[paota[i].x][paota[i].y] = 0;
}
rei(t);
} int kong()
{
rep1(i, 1, 6)
if (mayis[i].cunzai == 0)
return i;
return 233;
} void xinxi()
{
rep1(i, 1, 6)
if (mayis[i].cunzai)//如果有蚂蚁
{
int x = mayis[i].x, y = mayis[i].y;//
if (mayis[i].dangao)//如果这只蚂蚁身上有蛋糕就信息素加5
tu[x][y] += 5;
else//否则加2
tu[x][y] += 2;
}
} bool is(int x, int y)//判断这个点是不是蛋糕所在的点
{
return (x == n && y == m);
} int sqr(int x)
{
return x*x;
} void moni()
{
rep1(i, 1, 6)//一开始所有的蚂蚁都不存在
mayis[i].cunzai = 0;
get_dangao = 0;
rep1(T, 1, t)
{
if (now < 6 && can[0][0])//如果蚂蚁的个数小于6且蚂蚁窝的位置没有蚂蚁
{
now++;//增加一只蚂蚁
int po = kong();//找到可以新加蚂蚁的蚂蚁数组的下标
mayis[po].x = mayis[po].y = 0, mayis[po].cunzai = 1;//把这个蚂蚁加入
//记录坐标为0,0然后标记这只蚂蚁存在
mayis[po].id = ++tot, mayis[po].get_xue(tot), mayis[po].dangao = 0;
mayis[po].prex = mayis[po].prey = -1;
//tot是这只蚂蚁的id,即总共是第几只蚂蚁,通过这个tot能获得它的血量,然后一开始都没有蛋糕
mayis[po].age = 0;//一开始蚂蚁的年龄是0
can[0][0] = 0;//标记蚂蚁窝的位置有蚂蚁了
}
xinxi();//撒完信息素
//然后呢...然后移动
sort(mayis + 1, mayis + 1 + 6, cmp1);
//id小的先移动
rep1(i, 1, 6)
if (mayis[i].cunzai)//存在就可以移动
{
int tot = 0;
int x = mayis[i].x, y = mayis[i].y, cnt = 0, maxxinxi, cntju;
int tarx, tary;
rep1(j, 1, 4)//先往4个方向找,看看有没有可以走的点
{
int tx = x + dx[j], ty = y + dy[j];
if (tx<0 || tx>n) continue;
if (ty<0 || ty>m) continue;
if (tx == mayis[i].prex && ty == mayis[i].prey) continue;//不能是它之前待的位置
if (!can[tx][ty]) continue;
if (cnt == 0)//顺便找信息素最大的方向
{
maxxinxi = tu[tx][ty];
cntju = j;//记录信息素最大的方向
cnt = 1;//记录只有一个
}
else
{
if (maxxinxi < tu[tx][ty])//如果信息素更大就更新
{
maxxinxi = tu[tx][ty];//
cntju = j;
cnt = 1;
}
else
if (maxxinxi == tu[tx][ty])//如果和最大的信息素一样就增加最大信息素的方向个数
cnt++;
}
tarx = tx, tary = ty;//这是用于处理只有一个方向可以走的情况
tot += can[tx][ty];//记录有几个方向可以走
}
if (tot == 0)//如果没有可以走的点.那就只能待在原地了
//此时是5的倍数也无所谓了
{
mayis[i].prex = x, mayis[i].prey = y;
if (!get_dangao && is(x, y))//可能有蛋糕此时回到了n,m的位置
{
get_dangao = 1;//获得蛋糕
mayis[i].xue += int(mayis[i].chushi / 2);//增加血量
mayis[i].xue = min(mayis[i].xue, mayis[i].chushi);//不能超过上限
mayis[i].dangao = 1;//记录它获得蛋糕
}
}
else
if (tot == 1)//如果只有一个确认的方向可以走
//那么就算是5的倍数也是只能走这个方向
{
mayis[i].prex = x, mayis[i].prey = y;
can[x][y] = 1;//因为已经走开了,所以这个位置就可以走了
mayis[i].x = tarx, mayis[i].y = tary;//到了新的位置
if (!get_dangao && is(tarx, tary))//如果还没有蚂蚁拿到蛋糕且它在蛋糕位置
{
get_dangao = 1;//记录它拿到了蛋糕
mayis[i].xue += int(mayis[i].chushi / 2);//增加血量
mayis[i].xue = min(mayis[i].xue, mayis[i].chushi);//不能超过上限
mayis[i].dangao = 1;//记录它拿到了蛋糕
}
can[tarx][tary] = 0;//这个位置不能再走了
}
else//有多个方向可以走
{
if (cnt == 1)//如果信息量最多的那个只有一个
{
//那么方向就确定了即cntju
//这个时候如果是5的倍数就逆时针旋转
if (((mayis[i].age + 1) % 5) == 0)
{
while (1)
{
cntju--;
if (cntju < 1) cntju = 4;
int tx = x + dx[cntju], ty = y + dy[cntju];
if (tx<0 || tx>n) continue;
if (ty<0 || ty>m) continue;
if ((tx == mayis[i].prex) && (ty == mayis[i].prey)) continue;
if (!can[tx][ty]) continue;
//找到第一个可以走的方向
break;
}
}
//转到了那个合适的位置了
mayis[i].prex = x, mayis[i].prey = y;
can[x][y] = 1;//走开了
mayis[i].x = x + dx[cntju], mayis[i].y = y + dy[cntju];//新的位置
if (!get_dangao && is(mayis[i].x, mayis[i].y))
{
get_dangao = 1;
mayis[i].xue += int(mayis[i].chushi / 2);
mayis[i].xue = min(mayis[i].xue, mayis[i].chushi);
mayis[i].dangao = 1;
}
can[x + dx[cntju]][y + dy[cntju]] = 0;//这个位置不能走了
}
else
{
//信息素没办法判断了
//先从正东然后 顺时针旋转转到第一个可以选择的地方
rep1(j, 1, 4)
{
int tx = x + dx[j], ty = y + dy[j];
if (tx<0 || tx>n) continue;
if (ty<0 || ty>m) continue;
if ((tx == mayis[i].prex) && (ty == mayis[i].prey)) continue;
if (!can[tx][ty]) continue;
if (tu[tx][ty] != maxxinxi) continue;//信息素不是最大的那个不算的。。
cntju = j;
break;
}
if (((mayis[i].age + 1) % 5) == 0)//这个时候如果是5的倍数就逆时针旋转
{
while (1)
{
cntju--;
if (cntju < 1) cntju = 4;
int tx = x + dx[cntju], ty = y + dy[cntju];
if (tx<0 || tx>n) continue;
if (ty<0 || ty>m) continue;
if ((tx == mayis[i].prex) && (ty == mayis[i].prey)) continue;
if (!can[tx][ty]) continue;
break;
}
}
mayis[i].prex = x, mayis[i].prey = y;
can[x][y] = 1;//可以走了
mayis[i].x = x + dx[cntju], mayis[i].y = y + dy[cntju];//到了新位置
if (!get_dangao && is(mayis[i].x, mayis[i].y))//到了蛋糕位置,蛋糕没被拿走
{
get_dangao = 1;
mayis[i].xue += int(mayis[i].chushi / 2);
mayis[i].xue = min(mayis[i].xue, mayis[i].chushi);
mayis[i].dangao = 1;
}
can[x + dx[cntju]][y + dy[cntju]] = 0;//不能走了
}
}
}
//蚂蚁都移动完了.塔开始攻击
rep1(i, 1, s)
{//i枚举每一个塔
int which = -1, midis = -1;
rep1(j, 1, 6)//如果有这只蚂蚁
if (mayis[j].cunzai)
{
int x = mayis[j].x, y = mayis[j].y;
int dis = sqr(x - paota[i].x) + sqr(y - paota[i].y);//获取距离平方
if (dis <= sqr(r))//如果在攻击范围内
{
if (mayis[j].dangao)//如果是拿着蛋糕的那只,就直接攻击它了
{
which = j;
midis = dis;
break;
}
if (midis == -1)//否则选择距离最近的那只搞
{
midis = dis;
which = j;
}
else
{
if (dis < midis)
{
midis = dis;
which = j;
}
}
}
}
if (which == -1) continue;//没有一直蚂蚁能攻击到就跳过
int x = mayis[which].x - paota[i].x, y = mayis[which].y - paota[i].y;
int MXX = max(mayis[which].x, paota[i].x), tpx = min(mayis[which].x, paota[i].x);
int MXY = max(mayis[which].y, paota[i].y), tpy = min(mayis[which].y, paota[i].y); rep1(j, 1, 6)//
if (mayis[j].cunzai)//不要忘记判断这只蚂蚁是否存在
if (mayis[j].x >= tpx&&mayis[j].x <= MXX&&mayis[j].y >= tpy&&mayis[j].y <= MXY
&&fabs((mayis[j].x - paota[i].x)*y - (mayis[j].y - paota[i].y)*x) / sqrt(x*x + y*y) <= 0.5)
mayis[j].xue -= d; }
//攻击也完啦!
rep1(j, 1, 6)
if (mayis[j].cunzai)
{
if (mayis[j].xue < 0)
{
mayis[j].cunzai = 0;
if (mayis[j].dangao)
get_dangao = 0;
can[mayis[j].x][mayis[j].y] = 1;
now--;
}
} //printf("%d\n", get_dangao);
if (get_dangao != 0)
{
//如果拿着蛋糕的那只到了蚂蚁窝就结束啦
rep1(j, 1, 6)
if (mayis[j].cunzai && mayis[j].dangao&& mayis[j].x == 0 && mayis[j].y == 0)
{
printf("Game over after %d seconds\n", T);
return;
}
}
rep1(i, 0, n)
rep1(j, 0, m)
if (tu[i][j] > 0)
tu[i][j]--;
rep1(i, 1, 6)
if (mayis[i].cunzai)
{
mayis[i].age++;
}
//if (T == 7)
// break;
}
printf("The game is going on\n");
} void pre()
{
rep1(i, 0, 9)
rep1(j, 0, 9)
can[i][j] = 1;
} void o()
{
sort(mayis + 1, mayis + 1 + 6, cmp2);
printf("%d\n", now);
rep1(i, 1, 6)
if (mayis[i].cunzai)
cout << mayis[i].age << ' ' << ((mayis[i].id - 1) / 6) + 1 << ' ' << mayis[i].xue << ' ' << mayis[i].x << ' ' << mayis[i].y << endl;
} int main()
{
//printf("%f\n", d_zx(point{ 0,1 }, point{ 1,0 }, point{ 0,0 }));
//return 0;
//freopen("F:\\rush.txt", "r", stdin);
pre();
in();
moni();
o();
//printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}


【BZOJ 1033】 [ZJOI2008]杀蚂蚁antbuster(判断线段是否和圆相交)的更多相关文章

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

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

  2. [BZOJ 1033] [ZJOI2008] 杀蚂蚁antbuster 【模拟!】

    题目链接: BZOJ - 1033 题目分析 模拟!纯粹按照题目描述模拟! 这是一道喜闻乐见的经典模拟题! 我一共写了2遍,Debug 历时2天的所有晚自习 ... 时间超过 8h ... 我真是太弱 ...

  3. BZOJ 1033: [ZJOI2008]杀蚂蚁antbuster(模拟)

    坑爹的模拟题QAQ DEBUG多了1kb QAQ 按题意做就行了 注意理解题意啊啊啊啊 尼玛输出忘换行wa了3次QAQ CODE: #include<cstdio>#include< ...

  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. [ZJOI2008]杀蚂蚁antbuster 题解

    一个题目的可读版本:https://www.zybuluo.com/Jerusalem/note/221811 这两天做的又一道大模拟题,感觉这玩意有毒,会上瘾啊…… 比起猪国杀这道题真心不知道高到哪 ...

随机推荐

  1. Numpy库进阶教程(一)求解线性方程组

    前言 Numpy是一个很强大的python科学计算库.为了机器学习的须要.想深入研究一下Numpy库的使用方法.用这个系列的博客.记录下我的学习过程. 系列: Numpy库进阶教程(二) 正在持续更新 ...

  2. 【几何/数学】概念的理解 —— (非)刚体变换((non-)rigid transformation)

    1. 刚体变换与非刚体变换 What is a non-rigid transformation? 刚体变换(rigid transformation)一般分为如下几种: 平移对象,而不改变形状和大小 ...

  3. css使文本保留多个空格

    css属性: white-space: pre-wrap

  4. 大战C100K之-Linux内核调优篇--转载

    原文地址:http://joyexpr.com/2013/11/22/c100k-4-kernel-tuning/ 早期的系统,系统资源包括CPU.内存等都是非常有限的,系统为了保持公平,默认要限制进 ...

  5. Altium Designer敷铜的规则设定

    InPolygon 这个词是铺铜对其他网络的设置,铺铜要离其他网络远点,因为腐蚀不干净会对 电路板有影响... 问题一:: 如下图所示,现在想让敷铜与板子边界也就是keepoutlayer的间距小一点 ...

  6. js json简介(json的本质也是字符串)(用于服务器和客户端通信)

    js json简介(json的本质也是字符串)(用于服务器和客户端通信) 一.总结 1.json的语法和js的语法非常像,只是json的键和值都是双引号,因为json的本质也是字符串 2.json是一 ...

  7. 嵌入式arm linux环境中gdb+gdbserver调试

    一.前言嵌入式Linux系统中,应用开发过程中,很多情况下,用户需要对一个应用程序进行反复调试,特别是复杂的程序.采用GDB方法调试,由于嵌入式系统资源有限性,一般不能直接在目标系统上进行调试,通常采 ...

  8. 选择标识符(identifier)

    整数通常是标识列最好的选择,因为它们很快并且可以使用auto_increment:千万不要使用enum和set类型作为标识列:尽量避免使用字符串类型作为标识列,因为他们很消耗空间,并且通常比数字类型慢 ...

  9. iOS开发之Quartz2D 六 绘制UIImageView

    #import <UIKit/UIKit.h> @interface XMGImageView : UIView /** <#注释#> */ @property (nonato ...

  10. php实现求字符串第一个只出现一次的字符

    php实现求字符串第一个只出现一次的字符 一.总结 很简单的逻辑 1.两个数组,一个存字母,一个存字母出现的次数 二.php实现求字符串第一个只出现一次的字符 题目描述 在一个字符串(1<=字符 ...