FZU 2150 Fire Game BFS求解

来源:互联网 发布:ubuntu下载火狐浏览器 编辑:程序博客网 时间:2024/06/05 20:52

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2150

题意:给定一个草坪,两人分别点燃一个草堆(可以相同),求所有草堆都着火时的最小时间。

谈起这题也是有点悲催,TLE了好多次,看了其他人的题解再写,WA了好多次,今晚看到一篇不错的博客让我灵感来了,然后顺利AC。

这篇博客是:http://m.blog.csdn.net/blog/zzzz40/38122385,我也只是大概看了下就来灵感了,哈哈。。


所谓的灵感:大概看了下博客,发现他也是暴力枚举两个点,为什么他的就没有TLE呢?仔细一看,人家暴力的比我漂亮一点,漂亮之处在于把:

for(int i=0;i<(n*m);i++) for(int j=0;j<(n*m);j++)改为:for(int i=0;i<(n*m;i++) for(int j=i;j<(n*m);j++)。

这样一来,计算量变为了原来的1/2,你也许还会说时间复杂度不还是O((n*m)^2)吗?但实际上这样之后其实已经不会TLE了。问题是为什么这样改能够不TLE呢?看到一篇博客说,此题纯暴力的话时间复杂度会达到10^8,我也是半信半疑,毕竟对时间复杂度的计算不是很清楚。我对此题的时间复杂度的计算是:显然两个for循环的时间复杂度为O((m*n)^2)=10^4。然后计算BFS的时间复杂度:显然每层有一个for循环,循环量为4,最大层为对角线,为10层,这样总的复杂度为4^10,在乘上前面的复杂度,显然超时!但事实并不是这样,我们可以这样想,由矩形的形状可以推知,其实左上角和右下角的计算量应该是一个数量级的,为什么这样说呢?因为两者是对称的嘛,经过筛选后,留下的计算量应该是相等的。所以实际上的层数应该为5层。但是第一层已经作为了初始化入队了,循环量为0,只有4层了,这样一来总的时间复杂度为:10^4*(4^4)。约为:2.5*10^6。所以,在时间变为原来的1/2后(500ms+),才会AC,当然,我对计算机1s的运算量不是很清楚,从此题也可以估计出,大概也就10^6或是10^7的数量级,10^8应该会TLE。其实一开始我也觉得不应该TLE啊,可惜了我暴力的不够漂亮。。。。

还有一点,既然都这么暴力了,那么算不算连通块的数量也就变得没有意义了。

代码:

#include<iostream>#include<sstream>#include<cstring>#include<cstdio>#include<cmath>#include<algorithm>#include<queue>#include<set>#include<map>#include<vector>#include<string>#define LL __int64#define INF 0x7fffffffusing namespace std;struct node{    int x,y,step;};char Map[11][11];int vis[11][11];int n,m;int d[][2]={1,0,-1,0,0,1,0,-1};int bfs(int x,int y,int xx,int yy){    memset(vis,0,sizeof(vis));    vis[x][y]=vis[xx][yy]=1;    queue<node> Q;    Q.push((node){x,y,0});    Q.push((node){xx,yy,0});    int ans=-1;    while(!Q.empty()){        node tp=Q.front();        ans=max(ans,tp.step);        Q.pop();        for(int p=0;p<4;p++){            int tx=tp.x+d[p][0],ty=tp.y+d[p][1];            if(tx<0|| ty<0 || tx>=n || ty>=m) continue;            if(Map[tx][ty]=='.' || vis[tx][ty]) continue;            Q.push((node){tx,ty,tp.step+1});            vis[tx][ty]=1;        }    }    for(int i=0;i<n;i++) for(int j=0;j<m;j++)        if(Map[i][j]=='#' && vis[i][j]==0) return INF;    return ans;}int main(){    //freopen("D:\\in.txt","r",stdin);    int T;cin>>T;    for(int kase=1;kase<=T;kase++){        cin>>n>>m;        for(int i=0;i<n;i++) for(int j=0;j<m;j++)            cin>>Map[i][j];        int ans=INF;        for(int i=0;i<n*m;i++)            for(int j=i;j<n*m;j++)                if(Map[i/m][i%m]=='#' && Map[j/m][j%m]=='#')                    ans=min(bfs(i/m,i%m,j/m,j%m),ans);        printf("Case %d: %d\n",kase,ans==INF? -1:ans);    }    return 0;}



0 0