zoukankan      html  css  js  c++  java
  • 《杀蚂蚁》有感

    昨天下午给别人调了一会儿杀蚂蚁(炸精度了),于是乎自己心血来潮也想写写这道神题。

    写代码没费多久,主要都是调代码。调了三节课,时间这么短的原因是因为我是对着标程调的(直接把下午调过了的那份代码输出调试信息然后两边手动fc……)。感觉浪费了这么一道神题。

    总的来说,杀蚂蚁技术含量不高,唯一有点技术含量的就是判断线段与圆相交(计算几何)。其他的,就是个大模拟。不过细节很多,而且很多都是很难注意到的。

    判断线段与圆相交的时候我用的是特殊方法(只适用于本题)。

    因为蚂蚁都在整点上,而直径都是1,因此只要看那些离炮塔距离更近的蚂蚁即可。又因为是线段而不是直线,所以只有和Target蚂蚁在炮塔的同一侧的蚂蚁才会被打到,因此我就用了点积判同侧,最后再用叉积算点到直线距离。这是特殊方法,对于一般情况还是不适用的。

    这题细节真心很多,而且很多都让人猝不及防。比如:

    1. 所有炮塔同时开炮,所以蚂蚁被打到负血之后还可以被打,蚂蚁的死亡必须在炮塔攻击之后统一进行。

    2. 小心精度问题,选择最近的蚂蚁和线段与圆相交可能炸精度(虽然对于本题来说蚂蚁都在整点上线段与圆相交不太可能炸精度),我调别人的代码调了一个多小时就是因为前者炸精度了。垃圾O2优化。

    3. 蚂蚁的移动是有先后的,先动的蚂蚁可能会挡住后动的蚂蚁。

    4. 扛蛋糕不一定是在走了一步之后,有那种扛蛋糕的蚂蚁死了然后原地不动的蚂蚁扛上了蛋糕的事情(我就被这玩意儿坑了)。

    5. 线段与圆相交要小心写,不要写错。

    6. 蚂蚁的移动要小心,真的很麻烦。

    总之,虽然说是练了练代码能力,但是感觉还没有二逼平衡树、Mokia价值高(Mokia一开始打死不过,后来重写了才A的)。都怪我对着标程调,罪过罪过。

    最后贴个代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<algorithm>
      5 using namespace std;
      6 const int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
      7 const double eps=1e-6;
      8 struct ANTS{
      9     int age,life,level,bornlife,x,y,lastx,lasty;
     10     bool havecake;
     11     ANTS(){}
     12     bool operator<(const ANTS &a)const{
     13         return age>a.age;
     14     }
     15     void getcake(){
     16         havecake=true;
     17         life+=(bornlife>>1);
     18         if(life>bornlife)life=bornlife;
     19     }
     20 }a[1000010];
     21 struct TOWER{int x,y;}b[100010];
     22 void bornant();
     23 void leavesth();
     24 void moveants();
     25 void attack();
     26 void judgeend();
     27 void endofround();
     28 void printwin();
     29 void printlose();
     30 void moveit(int);
     31 bool can(int,int,int);
     32 void moveto(int,int,int);
     33 void trytoattack(int);
     34 double dis(int,int);
     35 double dis3(int,int,int);
     36 void hitant(int);
     37 void dieant(int);
     38 void maintainants();
     39 int dcmp(double,double);
     40 int n,m,k,d,r,in[1010][1010];
     41 bool ant[1010][1010],tow[1010][1010],lose;
     42 int tim,T;
     43 int cak;
     44 int cnt=0,head=1,tail=1;
     45 int main(){
     46 #define MINE
     47 #ifdef MINE
     48     freopen("antbuster_ex.in","r",stdin);
     49     freopen("antbuster_ex.out","w",stdout);
     50 #endif
     51     scanf("%d%d%d%d%d",&n,&m,&k,&d,&r);
     52     for(int i=1;i<=k;i++){
     53         scanf("%d%d",&b[i].x,&b[i].y);
     54         tow[b[i].x][b[i].y]=true;
     55     }
     56     scanf("%d",&T);
     57     for(tim=1;tim<=T;tim++){
     58         //printf("TIME:%d
    ",tim);
     59         bornant();//printf("1");
     60         leavesth();//printf("2");
     61         moveants();//printf("3");
     62         attack();//printf("4");
     63         judgeend();//printf("5");
     64         if(lose)break;
     65         endofround();//printf("6
    ");
     66         //printf("cnt=%d
    ",cnt);
     67         //printwin();printf("
    ");
     68     }
     69     if(lose)printlose();
     70     else printwin();
     71 #ifndef MINE
     72     printf("
    -------------------------DONE-------------------------
    ");
     73     for(;;);
     74 #endif
     75     return 0;
     76 }
     77 void bornant(){
     78     if(cnt<6&&!ant[0][0]){
     79         //printf("%d borns
    ",tail);
     80         cnt++;
     81         a[tail].age=1;
     82         a[tail].level=(tail-1)/6+1;
     83         a[tail].life=a[tail].bornlife=(int)(4*pow(1.1,a[tail].level));
     84         a[tail].x=a[tail].y=0;
     85         ant[0][0]=true;
     86         a[tail].lastx=a[tail].lasty=-1;
     87         tail++;
     88     }
     89 }
     90 void leavesth(){
     91     for(int i=head;i!=tail;i++){
     92         if(a[i].havecake)in[a[i].x][a[i].y]+=5;
     93         else in[a[i].x][a[i].y]+=2;
     94     }
     95 }
     96 void moveants(){
     97     for(int i=head;i!=tail;i++)moveit(i);
     98 }
     99 void attack(){
    100     for(int j=1;j<=k;j++)trytoattack(j);
    101     for(int i=head;i!=tail;i++)dieant(i);
    102 }
    103 void judgeend(){
    104     if(cak&&!a[cak].x&&!a[cak].y)lose=true;
    105     //    &   一开始没看出来......论逻辑与与按位与的差别......
    106 }
    107 void endofround(){
    108     /*for(int i=0;i<=n;i++){
    109         for(int j=0;j<=m;j++)printf("%d ",in[i][j]);
    110         printf("
    ");
    111     }printf("
    ");*/
    112     for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)if(in[i][j])in[i][j]--;
    113     for(int i=head;i!=tail;i++)a[i].age++;
    114     /*for(int i=0;i<=n;i++){
    115         for(int j=0;j<=m;j++)printf("%d ",in[i][j]);
    116         printf("
    ");
    117     }
    118     printf("
    ");
    119     for(int i=0;i<=n;i++){
    120         for(int j=0;j<=m;j++)printf("%d ",ant[i][j]);
    121         printf("
    ");
    122     }*/
    123 }
    124 void printwin(){
    125     printf("The game is going on
    ");
    126     printf("%d
    ",cnt);
    127     for(int i=head;i!=tail;i++){
    128         /*if(cak!=i)*/printf("%d %d %d %d %d
    ",a[i].age-1,a[i].level,a[i].life,a[i].x,a[i].y);
    129         //else printf("id=%d %d %d %d %d %d !!!cake
    ",i,a[i].age-1,a[i].level,a[i].life,a[i].x,a[i].y);
    130     }
    131 }
    132 void printlose(){
    133     printf("Game over after %d seconds
    ",tim);
    134     printf("%d
    ",cnt);
    135     for(int i=head;i!=tail;i++){
    136         printf("%d %d %d %d %d
    ",a[i].age-1,a[i].level,a[i].life,a[i].x,a[i].y);
    137     }
    138 }
    139 void moveit(int i){
    140     //printf("moveit(%d) at(%d,%d)
    ",i,a[i].x,a[i].y);
    141     bool ok[4]={false},OK=false;
    142     int x,y,tmp=0;
    143     for(int k=0;k<4;k++){
    144         x=a[i].x+dx[k];
    145         y=a[i].y+dy[k];
    146         ok[k]=can(x,y,i);
    147         //printf("x=%d y=%d ok=%d
    ",x,y,ok[k]);
    148         if(ok[k]){
    149             OK=true;
    150             if(in[x][y]>tmp){
    151                 //printf("clear ok
    ");
    152                 memset(ok,false,sizeof(ok));
    153                 ok[k]=true;
    154                 tmp=in[x][y];
    155             }
    156         }
    157     }
    158     //for(int k=0;k<4;k++)printf("%d ",ok[k]);printf("
    ");
    159     if(!OK){
    160         moveto(a[i].x,a[i].y,i);
    161         return;
    162     }
    163     if(a[i].age%5){//printf("-");
    164         for(int k=0;k<4;k++)if(ok[k]){
    165             moveto(a[i].x+dx[k],a[i].y+dy[k],i);
    166             break;
    167         }
    168     }
    169     else{//This is a bit complex...
    170         int k=0;//printf("--");
    171         for(;!ok[k];k++);
    172         for(k=(k+3)%4;!can(a[i].x+dx[k],a[i].y+dy[k],i);k=(k+3)%4);
    173         moveto(a[i].x+dx[k],a[i].y+dy[k],i);
    174     }
    175 }
    176 bool can(int x,int y,int i){
    177     if(x<0||y<0||x>n||y>m)return false;
    178     if(ant[x][y]||tow[x][y])return false;
    179     if(x==a[i].lastx&&y==a[i].lasty)return false;
    180     return true;
    181 }
    182 void moveto(int x,int y,int i){//and get cake.
    183     //printf("%d from (%d,%d) to (%d,%d)
    ",i,a[i].x,a[i].y,x,y);
    184     if(x==a[i].x&&y==a[i].y){
    185         a[i].lastx=a[i].lasty=-1;
    186         if(!cak&&x==n&&y==m){
    187             //printf("%d gets the cake
    ",i);
    188             a[i].getcake();
    189             cak=i;
    190         }
    191     }
    192     else{
    193         a[i].lastx=a[i].x;
    194         a[i].lasty=a[i].y;
    195         ant[a[i].x][a[i].y]=false;
    196         ant[x][y]=true;
    197         a[i].x=x;
    198         a[i].y=y;
    199         if(!cak&&x==n&&y==m){
    200             //a[i].havecake=true;
    201             //printf("%d gets the cake
    ",i);
    202             a[i].getcake();
    203             cak=i;
    204         }
    205     }
    206 }
    207 void trytoattack(int j){//Tower j trys to attack.
    208     //printf("trytoattack(%d)
    ",j);
    209     int target=0;
    210     if(cak&&dcmp(dis(cak,j),r)<=0)target=cak;
    211     if(!target){
    212         for(int i=head;i!=tail;i++)if(dcmp(dis(i,j),r)<=0&&(!target||dcmp(dis(i,j),dis(target,j))<0))target=i;
    213     }
    214     if(!target)return;
    215     hitant(target);
    216     //printf("hit target(%d)
    ",target);
    217     for(int i=head;i!=tail;i++)if(i!=target&&dcmp(dis(i,j),dis(target,j))<0&&dcmp(dis3(i,j,target),0.5)<=0){
    218         TOWER A,B;
    219         A.x=a[target].x-b[j].x;
    220         A.y=a[target].y-b[j].y;
    221         B.x=a[i].x-b[j].x;
    222         B.y=a[i].y-b[j].y;
    223         if(A.x*B.x+A.y*B.y<=0)continue;
    224         hitant(i);
    225     }
    226 }
    227 double dis(int i,int j){//The distance of ant i and tower j
    228     return sqrt((a[i].x-b[j].x)*(a[i].x-b[j].x)+(a[i].y-b[j].y)*(a[i].y-b[j].y));
    229 }
    230 double dis3(int i,int j,int ii){//Ant i's distance to the tower hitting ii
    231     TOWER A,B;//In fact these are only two points,2333
    232     A.x=a[i].x-b[j].x;
    233     A.y=a[i].y-b[j].y;
    234     B.x=a[ii].x-a[i].x;
    235     B.y=a[ii].y-a[i].y;
    236     return abs(A.x*B.y-B.x*A.y)/dis(ii,j);
    237 }
    238 void hitant(int i){
    239     //printf("%d is hitted
    ",i);
    240     a[i].life-=d;
    241     //if(a[i].life<0)dieant(i);
    242 }
    243 void dieant(int x){
    244     if(a[x].life>=0)return;
    245     //printf("%d die
    ",x);
    246     if(a[x].havecake)cak=0;
    247     ant[a[x].x][a[x].y]=false;
    248     swap(a[head],a[x]);
    249     head++;
    250     cnt--;
    251     maintainants();
    252 }
    253 void maintainants(){
    254     sort(a+head,a+tail);
    255     cak=0;
    256     for(int i=head;i!=tail;i++)if(a[i].havecake)cak=i;
    257 }
    258 int dcmp(double a,double b){
    259     if(fabs(a-b)<=eps)return 0;
    260     return a<b?-1:1;
    261 }
    262 /*
    263 8 8
    264 2 10 1
    265 7 8
    266 8 6
    267 5
    268 Answer:
    269 The game is going on
    270 5
    271 5 1 4 1 4
    272 4 1 4 0 4
    273 3 1 4 0 3
    274 2 1 4 0 2
    275 1 1 4 0 1
    276 */
    View Code

    16.10.16 Sun.

  • 相关阅读:
    WCF中的ServiceHost初始化两种方式(宿主)
    WCF实例上下文以及会话学习
    MSSQL有关时间函数知识(转)
    [转载红鱼儿]kbmmw 开发点滴:kbmMW缓存机制
    [转载红鱼儿]kbmmw 开发点滴:kbmMWEventService的本质
    [转载红鱼儿]kbmmw 开发点滴:ErrorTable用法
    [转载红鱼儿]kbmmw 开发点滴:kbmMW客户端提交事务的现场处理
    [转载红鱼儿]kbmmw 开发点滴:解决QueryService重复查询问题
    [转载红鱼儿]kbmmw 开发点滴:TkbmMWLock用法
    [转载红鱼儿]kbmmw 开发点滴:Authorization failed.
  • 原文地址:https://www.cnblogs.com/hzoier/p/5965876.html
Copyright © 2011-2022 走看看