首页 > 代码库 > NOIP模拟题——集结蚂蚁
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 else108 {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 else125 {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 else137 printf("%d",ans);138 return 0;139 }
NOIP模拟题——集结蚂蚁