1: 在西面有墙
2: 在北面有墙
4: 在东面有墙
8: 在南面有墙
选择最佳的墙来推倒。有多解时选最靠西的,仍然有多解时选最靠南的。同一格子北边的墙比东边的墙更优先。
用该墙的南邻单位的北墙或西邻单位的东墙来表示这面墙,方法是输出邻近单位的行数、列数和墙的方位("N"(北)或者"E"(东))。
考前就用这道题来复习一下dfs和bfs吧
1.对于这道题,之前就写过,不过没有那两行输出,多了那两行我的LJbfs就超时了。
2.这道题也是很考验看题能力的,反正我是看漏了很多条件
3.这道题用位运算可以省去一些不必要的判断。。。
1 int dx[6]={0,1,0,-1}; 2 int dy[6]={1,0,-1,0}; 3 int a[6]={1,2,4,8}; 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 if(fire[i][j]&a[k])
首先附上70分的超时代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 int map[2000][2000],fire[2000][2000]; 7 int dx[6]={0,1,0,-1}; 8 int dy[6]={1,0,-1,0}; 9 int a[6]={1,2,4,8}; 10 int s,num,ans=1,n,m; 11 void bfs(int p,int q) 12 { 13 int h[2000][3]; 14 h[1][1]=p;h[1][2]=q; 15 map[p][q]=1; 16 int head=0,tail=1,x,y; 17 num++; 18 s=1; 19 do 20 { 21 head++; 22 for(int i=0;i<=3;++i) 23 { 24 x=h[head][1]+dx[i]; 25 y=h[head][2]+dy[i]; 26 if(x>0&&x<=n&&y>0&&y<=m&&map[x][y]==0&&(fire[x][y]&a[i])==0) 27 { 28 tail++; 29 s++; 30 ans=max(ans,s); 31 map[x][y]=1; 32 h[tail][1]=x; 33 h[tail][2]=y; 34 } 35 } 36 }while(head<tail); 37 } 38 int main() 39 { 40 scanf("%d%d",&m,&n); 41 for(int i=1;i<=n;++i) 42 { 43 for(int j=1;j<=m;++j) 44 { 45 scanf("%d",&fire[i][j]); 46 map[i][j]=0; 47 } 48 } 49 for(int i=1;i<=n;++i) 50 { 51 for(int j=1;j<=m;++j) 52 { 53 if(!map[i][j]) bfs(i,j); 54 } 55 } 56 printf("%d\n%d\n",num,ans); 57 int maxx=ans,hang,lie,qiang; 58 for(int j=1;j<=m;++j) 59 { 60 for(int i=n;i>=1;--i) 61 { 62 for(int k=0;k<=3;++k) 63 { 64 if(k==1||k==2) 65 { 66 memset(map,0,sizeof(map)); 67 if(fire[i][j]&a[k]) 68 { 69 fire[i][j]-=a[k]; 70 if(k==1) fire[i+1][j]-=a[3]; 71 if(k==2) fire[i][j+1]-=a[0]; 72 for(int x=1;x<=n;++x) 73 { 74 for(int y=1;y<=m;++y) 75 { 76 if(!map[x][y]) bfs(x,y); 77 } 78 } 79 if(ans>maxx) 80 { 81 maxx=ans; 82 hang=i; 83 lie=j; 84 qiang=k; 85 } 86 fire[i][j]+=a[k]; 87 if(k==1) fire[i+1][j]+=a[3]; 88 if(k==2) fire[i][j+1]+=a[0]; 89 } 90 } 91 } 92 } 93 } 94 printf("%d\n%d %d ",maxx,hang,lie); 95 if(qiang==1) printf("N"); 96 if(qiang==2) printf("E"); 97 return 0; 98 }
上面那串可以忽略,着急什么都不想就瞎写
下面附上正解:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int map[2000][2000],fire[2000][2000]; 6 int dx[6]={0,1,0,-1}; 7 int dy[6]={1,0,-1,0}; 8 int a[6]={1,2,4,8}; 9 int num,ans=1,n,m; 10 int c[5000]; //用来存储连通块的大小 11 int wei[2000][2000]; //用来存储房间所属连通块 12 void bfs(int p,int q,int shu) 13 { 14 int h[2000][3]; 15 h[1][1]=p;h[1][2]=q; 16 map[p][q]=1; 17 wei[p][q]=shu; 18 int head=0,tail=1,x,y; 19 num++; 20 c[shu]=1; 21 do 22 { 23 head++; 24 for(int i=0;i<=3;++i) 25 { 26 x=h[head][1]+dx[i]; 27 y=h[head][2]+dy[i]; 28 if(x>0&&x<=n&&y>0&&y<=m&&map[x][y]==0&&(fire[x][y]&a[i])==0) 29 { 30 tail++; 31 c[shu]++; 32 ans=max(ans,c[shu]); 33 map[x][y]=1; 34 wei[x][y]=shu; 35 h[tail][1]=x; 36 h[tail][2]=y; 37 } 38 } 39 }while(head<tail); 40 } 41 int main() 42 { 43 scanf("%d%d",&m,&n); 44 for(int i=1;i<=n;++i) 45 { 46 for(int j=1;j<=m;++j) 47 { 48 scanf("%d",&fire[i][j]); 49 map[i][j]=0; 50 } 51 } 52 int cnt=0; 53 for(int i=1;i<=n;++i) 54 { 55 for(int j=1;j<=m;++j) 56 { 57 if(!map[i][j]) bfs(i,j,++cnt); 58 } 59 } 60 printf("%d\n%d\n",num,ans); 61 int maxx=ans,hang,lie,qiang; 62 for(int j=1;j<=m;++j) 63 { 64 for(int i=n;i>=1;--i) 65 { 66 for(int k=1;k<=2;++k) 67 { 68 if(fire[i][j]&a[k]) 69 { 70 if(k==1&&wei[i][j]!=wei[i-1][j]) ans=c[wei[i][j]]+c[wei[i-1][j]]; 71 if(k==2&&wei[i][j]!=wei[i][j+1]) ans=c[wei[i][j]]+c[wei[i][j+1]]; 72 if(ans>maxx) 73 { 74 maxx=ans; 75 hang=i; 76 lie=j; 77 qiang=k; 78 } 79 } 80 } 81 } 82 } 83 printf("%d\n%d %d ",maxx,hang,lie); 84 if(qiang==1) printf("N"); 85 if(qiang==2) printf("E"); 86 return 0; 87 }