P1457 【城堡 The Castle】
阿新 • • 發佈:2018-11-08
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 }