您的位置:首页 > 其它

【BZOJ1033】[ZJOI2008]杀蚂蚁antbuster【模拟】

2016-03-06 14:07 405 查看
(´;ω;`)

有以下几点要注意:

1,蚂蚁不是质点。

2,蚂蚁的直径是1,不是半径是1。

3,给蚂蚁按age排序的时候,不要忘了target也得跟着变。

4,过早优化就是死,直接维护信息素的值就好了,每回合都O(nm)减一次,不要想着用时间戳。

5,蚂蚁上次移动位置的更新要注意放对位置,因为下面可能还有check相邻位置能不能走。

6,注意target的更新位置。

7,炮塔是一起攻击的,所以就算某只蚂蚁的血被打成了负,还是要被攻击。

8,判断激光是否能扫到其他蚂蚁的时候,注意double运算的精度,因为开了-O2,所以很可能出问题。返回类型为double的函数不要开inline,不要放在struct内。

⑨,大程序就不要缩行了。

/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int maxn = 10, maxs = 25, maxa = 10, inf = 0x3f3f3f3f;
const double eps = 1e-5;

const int maxant = 6;
const int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};

inline int sqr(int x) {
return x * x;
}

inline int dis(int x1, int y1, int x2, int y2) {
return sqr(x1 - x2) + sqr(y1 - y2);
}

double getcos(int x1, int y1, int x2, int y2, int x3, int y3) {
int a1 = x1 - x2, b1 = y1 - y2, a2 = x3 - x2, b2 = y3 - y2;
return (a1 * a2 + b1 * b2) / (double)(sqrt(dis(x1, y1, x2, y2)) * sqrt(dis(x3, y3, x2, y2)));
}

struct _game {

struct _turret {
int x, y;

_turret() {
x = y = 0;
}
};

struct _ant {
int x, y, oldx, oldy;
int age, level, inithealth, health;
bool dead;

_ant() {
x = y = oldx = oldy = 0;
age = level = inithealth = health = 0;
dead = 1;
}

bool operator < (const _ant &a) const {
if(dead) return 0;
if(a.dead) return 1;
return age > a.age;
}
};

int n, m, g[maxn][maxn], target;
bool blocked[maxn][maxn], over;

int turretcnt, damage, radius;
_turret turret[maxs];

int antcnt, antsum;
_ant ant[maxa];

void init() {
n = m = over = target = turretcnt = damage = radius = antcnt = antsum = 0;
for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) g[i][j] = blocked[i][j] = 0;

scanf("%d%d", &n, &m);
scanf("%d%d%d", &turretcnt, &damage, &radius);
for(int i = 1; i <= turretcnt; i++) {
int x, y; scanf("%d%d", &x, &y);
turret[i].x = x; turret[i].y = y;
blocked[x][y] = 1;
}
}

void antsort() {
for(int i = 1; i <= maxant; i++) for(int j = i + 1; j <= maxant; j++)
if(ant[j] < ant[i]) {
swap(ant[j], ant[i]);
if(target == i) target = j;
else if(target == j) target = i;
}
}

void spawnant() {
if(antcnt < maxant && !blocked[0][0]) {
antcnt++; antsum++;
for(int i = 1; i <= maxant; i++)
if(ant[i].dead) {
ant[i].x = ant[i].y = ant[i].oldx = ant[i].oldy = 0;
ant[i].age = 1;
ant[i].level = (antsum - 1) / 6 + 1;
ant[i].inithealth = int(4 * pow(1.1, ant[i].level));
ant[i].health = ant[i].inithealth;
ant[i].dead = 0;
blocked[0][0] = 1;
break;
}
}
antsort();
}

bool check(int x, int y, int id) {
if(x < 0 || x > n || y < 0 || y > m) return 0;
if(blocked[x][y]) return 0;
if(x == ant[id].oldx && y == ant[id].oldy) return 0;
return 1;
}

void move(int id) {
int dir, maxinfo = -1, x = ant[id].x, y = ant[id].y;
for(int i = 0; i < 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if(!check(xx, yy, id)) continue;
maxinfo = max(maxinfo, g[xx][yy]);
}
if(maxinfo == -1) {
ant[id].oldx = ant[id].x;
ant[id].oldy = ant[id].y;
return;
}
for(int i = 0; i < 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if(!check(xx, yy, id)) continue;
if(g[xx][yy] == maxinfo) {
dir = i;
break;
}
}
if(ant[id].age % 5 == 0)
for(int i = (dir - 1 + 4) % 4; i != dir; i = (i - 1 + 4) % 4) {
int xx = x + dx[i], yy = y + dy[i];
if(!check(xx, yy, id)) continue;
dir = i;
break;
}
ant[id].oldx = ant[id].x;
ant[id].oldy = ant[id].y;
blocked[ant[id].x][ant[id].y] = 0;
ant[id].x += dx[dir];
ant[id].y += dy[dir];
blocked[ant[id].x][ant[id].y] = 1;
return;
}

void makeinfo() {
for(int i = 1; i <= antcnt; i++)
g[ant[i].x][ant[i].y] += 2 + (target == i) * 3;
}

void moveant() {
for(int i = 1; i <= antcnt; i++)
move(i);
}

void checkcake() {
if(target) return;
for(int i = 1; i <= antcnt; i++)
if(ant[i].x == n && ant[i].y == m) {
target = i;
ant[i].health = min(ant[i].inithealth, ant[i].health + ant[i].inithealth / 2);
}
}

int pdisp(int turid, int antid) {
return dis(turret[turid].x, turret[turid].y, ant[antid].x, ant[antid].y);
}

bool reached(int turid, int antid, int inno) {
double cos1 = getcos(ant[inno].x, ant[inno].y, turret[turid].x, turret[turid].y, ant[antid].x, ant[antid].y);
double cos2 = getcos(ant[inno].x, ant[inno].y, ant[antid].x, ant[antid].y, turret[turid].x, turret[turid].y);
if(cos1 < eps || cos2 < eps) return 0;
double d = sqrt(dis(ant[inno].x, ant[inno].y, turret[turid].x, turret[turid].y)) * sqrt(1.0 - cos1 * cos1);
return d - 0.5 < eps;
}

void attack() {
for(int i = 1; i <= turretcnt; i++) {
if(target && pdisp(i, target) <= sqr(radius)) {
for(int j = 1; j <= antcnt; j++) if(reached(i, target, j))
ant[j].health -= damage;
} else {
int id = 0, range = inf;
for(int j = 1; j <= antcnt; j++) if((pdisp(i, j) < range || (pdisp(i, j) == range && ant[id].age < ant[j].age))) {
range = pdisp(i, j);
id = j;
}
if(range > sqr(radius)) continue;
ant[id].health -= damage;
}
}
}

void checkdead() {
for(int i = 1; i <= maxant; i++)
if(!ant[i].dead && blocked[ant[i].x][ant[i].y] && ant[i].health < 0) {
ant[i].dead = 1;
antcnt--;
blocked[ant[i].x][ant[i].y] = 0;
}
if(target && ant[target].dead) target = 0;
}

void checkover() {
if(!ant[target].dead && ant[target].x == 0 && ant[target].y == 0)
over = 1;
}

void checkant() {
for(int i = 1; i <= maxant; i++) if(!ant[i].dead) ant[i].age++;
}

void checkmap() {
for(int i = 0; i <= n; i++) for(int j = 0; j <= m; j++) if(g[i][j])
g[i][j]--;
}

bool update() {
spawnant();
makeinfo();
moveant();
checkcake();
attack();
checkdead();
checkover();
if(over) return 0;
checkant();
checkmap();
return 1;
}

void print() {
printf("%d\n", antcnt);
antsort();
for(int i = 1; i <= antcnt; i++)
printf("%d %d %d %d %d\n", ant[i].age - 1, ant[i].level, ant[i].health, ant[i].x, ant[i].y);
}

} antbuster;

int main() {
antbuster.init();
int x, T; scanf("%d", &T);

for(x = 1; x <= T; x++)
if(!antbuster.update()) break;

if(x == T + 1) printf("The game is going on\n");
else printf("Game over after %d seconds\n", x);
antbuster.print();

return 0;
}


几组数据:

2.in

4 4
4 10 5
1 1
2 2
1 2
2 1
1000
2.out

Game over after 831 seconds
6
110 49 86 2 3
88 49 26 0 1
77 49 286 3 1
58 50 29 0 0
22 50 419 4 3
10 50 469 3 2


6.in

6 4
1 10000 10
2 2
256
6.out

The game is going on
0


7.in
4 7
0 0 0
60200
7.out

Game over after 60200 seconds
6
60199 1 4 0 0
60198 1 4 2 6
60197 1 4 4 7
60196 1 4 2 1
60195 1 4 3 5
60194 1 4 4 5


一组大数据

8.in

2 5
6 1 3
0 1
1 1
1 3
1 4
2 3
2 4
200000
8.out

The game is going on
6
15311 86 13525 1 5
12518 86 10203 0 5
9447 87 12495 0 4
6371 87 13461 0 3
3295 87 14586 0 2
219 87 15873 1 2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  模拟 杀蚂蚁