【总结】bfs

A. [USACO18OPEN,Silver]Multiplayer Moo

解析:这题挺水的。

首先跑一个bfs求连通块,附上对应的连通块标号,大小,颜色(及数字)。对相邻的连通块连边。然后枚举选择的两个颜色,对这两种颜色的连通块再求一次连通块即可。

乍一看时间复杂度 O ( m 2 c n t ) O(m^2cnt) O(m2cnt),其中cnt是连通块数目,m是颜色数目。而 c n t , m < = 25 0 2 cnt,m<=250^2 cnt,m<=2502,显然超时。

cnt是不能优化的,这是求连通块的时间代价。而枚举m时可以只枚举颜色数前50个大的,这样就过了。

#include<cstdio> #include<queue> #include<algorithm> #include<cstring> #include<map> using namespace std; const int N=255,M=255*255; map<int,int> mp; int ans,n,cnt,con[N][N],a[N][N],col[M],siz[M],lsh[M],num,sum[M]; int dx[5]={-1,0,1,0},dy[5]={0,1,0,-1}; bool pos[M]; vector<int> son[M]; bool cmp(int x,int y) { return sum[x]>sum[y]; } void bfs(int x,int y) { queue<pair<int,int> > q; q.push(make_pair(x,y)); con[x][y]=++cnt; col[cnt]=a[x][y]; siz[cnt]=1; while(q.size()) { int x=q.front().first,y=q.front().second; q.pop(); for(int i=0;i<4;i++) { int tx=x+dx[i],ty=y+dy[i]; if(!con[tx][ty]&&a[x][y]==a[tx][ty]) { q.push(make_pair(tx,ty)); con[tx][ty]=cnt; siz[cnt]++; } } } } void bfs2(int x,int a,int b) { int tot=siz[x]; queue<int> q; q.push(x); pos[x]=1; while(q.size()) { int x=q.front();q.pop(); for(int i=0;i<son[x].size();i++) { int y=son[x][i]; if(!pos[y]&&y>0&&(col[y]==lsh[a]||col[y]==lsh[b])) { q.push(y); pos[y]=1; tot+=siz[y]; } } } ans=max(ans,tot); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); if(!mp[a[i][j]]) { mp[a[i][j]]=++num; lsh[num]=num; } a[i][j]=mp[a[i][j]]; sum[a[i][j]]++; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(!con[i][j]) { bfs(i,j); ans=max(ans,siz[con[i][j]]); } } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { for(int s=0;s<4;s++) { int k=i+dx[s],l=j+dy[s]; int x=con[i][j],y=con[k][l]; if(x!=y) { son[x].push_back(y); son[y].push_back(x); } } } printf("%d\n",ans); sort(lsh+1,lsh+1+num,cmp); for(int i=1;i<=min(num,50);i++) { for(int j=1;j<=min(num,50);j++) { if(i==j) continue; for(int k=1;k<=cnt;k++) pos[k]=0; for(int k=1;k<=cnt;k++) { if(!pos[k]&&(col[k]==lsh[i]||col[k]==lsh[j])) { bfs2(k,i,j); } } } } printf("%d",ans); }

B. 1-04D. 膨胀的tyx

解析:一道中规中矩的搜索题。

显然只在给定的图中遍历,用(x,y,h,l)四元组表示状态,其中(h,l)表示在大的平面内的横纵坐标。从起点开始bfs,x>n则h++,x=0则h --;y>n则l++,y=0则l --。

当到达以前走过的点时,判断h,l是否相等,不相等则输出No;否则不加入队列(重复状态)。搜索结束后就输出Yes。

#include<bits/stdc++.h> using namespace std; const int N=2005; struct node{ int x,y,h,l; }st; int n,m,h[N][N],l[N][N],pos[N][N]; int dx[5]={-1,0,1,0},dy[5]={0,1,0,-1}; char s[N][N]; void bfs() { queue<node> q; q.push(st); pos[st.x][st.y]=1; while(q.size()) { node x=q.front();q.pop(); //printf("%d %d %d %d\n",x.x,x.y,x.l,x.h); for(int i=0;i<4;i++) { node y=x; int tx=y.x+dx[i],ty=y.y+dy[i]; if(tx>n) tx-=n,y.h++; if(tx==0) tx+=n,y.h--; if(ty>m) ty-=m,y.l++; if(ty==0) ty+=m,y.l--; y.x=tx; y.y=ty; if(s[tx][ty]=='#') continue; if(!pos[tx][ty]) { pos[tx][ty]=1; l[tx][ty]=y.l; h[tx][ty]=y.h; q.push(y); } else if(y.l!=l[tx][ty]||y.h!=h[tx][ty]) { printf("Yes"); exit(0); } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>s[i][j]; if(s[i][j]=='S') st.x=i,st.y=j; } bfs(); printf("No"); }

C. [树声前锋杯] E 小马过河

不会。

input: 50 1250 50 100 50 50 50 50 100 100 50 100 50 100 50 100 100 50 100 100 50 100 50 100 50 50 50 100 50 100 50 50 50 50 100 50 100 50 100 50 50 100 50 50 50 50 50 50 50 50 100 100 output: 3

D. 2-04D. 懒得说话的tyx

解析:这道题我是用数位dp做的。

注意前导0,正常的数位dp中都用dfs中参数z表示是否有前导0,这里我把它拆分成f1和f2,f1没有前导零,f2有前导零。

#include<cstdio> #include<algorithm> using namespace std; const int N=1e5+5; //11111110111010 //111111101110 int n,m,f1[101][N],f2[16][N],g[16],len,tot; int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) f1[1][i]=1; for(int i=0;i<n;i++) f2[1][i]=1; g[1]=1; f2[0][0]=1; for(int i=2;i<=15;i++) g[i]=g[i-1]*10%m; for(len=1;len<=15;len++) { if(f1[len][0]) break; for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { f1[len+1][(i*10+j)%m]|=f1[len][i]; f2[len+1][(i*10+j)%m]|=f2[len][i]; } } } //printf("%d\n",len); for(int i=1;i<=len;i++) { //printf("%d\n",tot); for(int j=0;j<n;j++) { if(i==1&&j==0) continue; if(f2[len-i][(tot-(j*g[len-i+1]%m)+m)%m]) { printf("%d",j); tot=(tot-(j*g[len-i+1]%m)+m)%m; break; } } } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530398.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(36)  评论(0编辑  收藏  举报  
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示