zoukankan      html  css  js  c++  java
  • NOIP模拟题——集结蚂蚁

    【题目描述】
    雄心勃勃的企业家达伦·克劳斯发现了皮姆博士有关缩小原子间距离的公式并
    研发出新一代微型“黄蜂战士”,皮姆博士担忧武器会引发不可挽回的后果,于是
    找到斯科特并使他成为了新一代“蚁人”。正逢克劳斯与外商交易黄蜂战衣的那天,
    斯科特受命前往摧毁黄蜂战衣并销毁数据,然而一个人的力量是渺小的,斯科特需
    要走入一个巨大的蚁穴去召唤蚂蚁与他共同作战。

    蚁穴是一个巨大复杂的地带,由n 行m 列组成,每个偶数行存在至少一个蚂蚁
    聚集地,同一行的不同蚂蚁聚集地以一堵墙隔开,每个蚂蚁聚集地的大小为Si;
    每个奇数行存在连接相邻偶数行中蚂蚁聚集地的路径,一个蚂蚁聚集地可能有多条
    路径可以到达。
    蚁人可从蚁穴的第一行任何一路口出发,由于时间紧迫,蚁人只能向下一行走,
    在这种情况下,蚁人希望你能告诉他如何使经过的蚂蚁聚集地大小之和最大,从而
    召唤最多的蚂蚁。
    【输入】
    第1 行包含两个用空格隔开的整数n,m,意义见描述。
    第2 到n+1 行,每行m 个字符(无间隔)且仅存在0 和1:同一偶数行中连
    续x 个0 组成一个大小为x 的蚂蚁聚集地,1 为墙体;奇数行中0 表示蚁人可以从
    此处通过。
    【输出】
    对于每组数据输出一个整数,表示经过路径中最大聚集地之和(不包含聚集
    地之间的路径)。若蚁人无法到达最后一行则请输出“-1”。
    4
    【输入样例】
    10 10
    1111101111
    1100001011
    1101111111
    1100000101
    1110110111
    1000110001
    1101111011
    1101000011
    1101011111
    1101010001
    【输出样例】
    17
    【样例解释】

    【数据规模】
    对于20%的数据,n≤20,m≤20
    对于50%的数据,n≤20,m≤100
    对于100%的数据,n≤5000,m≤2000,保证n 是一个偶数,路径的数量不多于1×106

     在输入的时候存每一行连续0的个数,若其中有一个0上面也是0(即是可以走的),便更新它的权值,到最后或碰到1时,看上一个可行点

    是否可以更改权值。

    后面直接就每一行每一行搜索了,由于存的是区间,每个区间只扫一次,所以最大时间复杂度O(mn)。

    好像用建图SPFA做也可以。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 using namespace std;
      5 const int maxn=5005;
      6 const int maxm=2005;
      7 int map[maxn][maxm];//1000w
      8 int pos[maxn][maxm>>1];//500w(不连在一起的位置)
      9 int f[maxn][maxm];//1000w
     10 int w[maxn][maxm>>1];//500w
     11 int n,m;
     12 int main()
     13 {
     14     freopen("ant.in","r",stdin);
     15     freopen("ant.out","w",stdout);
     16     scanf("%d%d",&n,&m);
     17     int t=0;int pre=1;bool pd=false;
     18     for(int i=1;i<=n;i++)
     19     {
     20         t=0;
     21         for(int j=1;j<=m;j++)
     22         {
     23             char c=getchar();
     24             while(c!='0'&&c!='1')c=getchar();
     25             map[i][j]=c-'0';
     26             
     27             
     28             if(i==1)continue;
     29             
     30             if(map[i][j]==0)
     31             t++;
     32             if(map[i][j]==1&&pd==false){t=0;continue;}
     33             if(map[i][j]==1&&pos[i][pos[i][0]]+t>=j&&pd==true)
     34             {
     35                 w[i][pos[i][0]]=t;
     36                 t=0;pd=false;
     37             }
     38             if(map[i][j]==0&&map[i-1][j]==0)//可以标记
     39             {
     40                 pd=true;
     41                 if(pos[i][0]==0)
     42                 {
     43                     pos[i][++pos[i][0]]=j;
     44                     w[i][pos[i][0]]=t;
     45                 }
     46                 else if(pos[i][pos[i][0]]+t-1>=j)
     47                 {
     48                     pos[i][pos[i][0]]=j;
     49                 }
     50                 else
     51                 pos[i][++pos[i][0]]=j; 
     52             }
     53             if(pd==true&&j==m&&map[i][j]==0)
     54             {
     55                 w[i][pos[i][0]]=t;
     56             }
     57         }
     58     }
     59     for(int i=1;i<=m;i++)
     60     f[1][i]=-1;
     61     for(int i=2;i<=n;i++)
     62     for(int j=1;j<=pos[i][0];j++)
     63     {
     64         if(i%2==0)//聚集地
     65         {
     66             if(i!=2)
     67             {
     68                 int k=pos[i][j];int k2=pos[i][j];
     69                 int v=w[i][j];int er=0;
     70                 while(map[i][k]==0)
     71                 {
     72                     if(k==0)break;
     73                     er=max(er,f[i-1][k]);
     74                     k--;
     75                 }k++;
     76                 while(map[i][k2]==0)
     77                 {
     78                     if(k2==m+1)break;
     79                     er=max(er,f[i-1][k]);
     80                     k2++;
     81                 }k2--;
     82                 if(er==0)continue;
     83                 else
     84                 {
     85                     for(int as=k;as<=k2;as++)
     86                     f[i][as]=er+v;
     87                 }
     88             }
     89             else
     90             {
     91                 int k=pos[i][j];int k2=pos[i][j];
     92                 int v=w[i][j];
     93                 while(map[i][k]==0)
     94                 {
     95                     if(k==0)break;
     96                     k--;
     97                 }k++;
     98                 while(map[i][k2]==0)
     99                 {
    100                     if(k2==m+1)break;
    101                     k2++;
    102                 }k2--;
    103                 for(int as=k;as<=k2;as++)
    104                 f[i][as]=v;
    105             }
    106         }
    107         else
    108         {
    109             int k=pos[i][j];int k2=pos[i][j];
    110             int v=f[i-1][pos[i][j]];
    111             while(map[i][k]==0)
    112             {
    113                 if(k==0)break;
    114                 v=max(f[i-1][k],v);
    115                 k--;
    116             }k++;
    117             while(map[i][k2]==0)
    118             {
    119                 if(k2==m+1)break;
    120                 v=max(f[i-1][k2],v);
    121                 k2++;
    122             }k2--;
    123             if(v==0)continue;
    124             else
    125             {
    126                 for(int as=k;as<=k2;as++)
    127                 f[i][as]=v;
    128             }
    129         } 
    130     }
    131     int ans=0;
    132     for(int i=1;i<=m;i++)
    133     if(f[n][i]>ans)ans=f[n][i];
    134     if(ans==0)
    135     printf("-1");
    136     else
    137     printf("%d",ans);
    138     return 0;
    139 } 
  • 相关阅读:
    如何创建一个基于 .NET Core 3 的 WPF 项目
    阅读源码系列
    近期计划
    Redis 源码走读(二)对象系统
    Redis 源码走读(一)事件驱动机制与命令处理
    basic paxos解析
    ThreadLocal深度解析
    MySQL InnoDB MVCC深度分析
    java泛型详解
    内存可见性,指令重排序,JIT。。。。。。从一个知乎问题谈起
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/6025932.html
Copyright © 2011-2022 走看看