通信ブロックDFSを求めて
最初の質問:HDU1241オイル預金
問題の説明
GeoSurvComp地質調査会社は、地下の石油鉱床を検出するための責任があります。GeoSurvCompは、一度に土地の一つの大きな矩形領域で動作し、そして多数の正方形のプロットに土地を分割するグリッドを作成します。次にプロットは油が含まれているか否かを決定するために感知装置を使用して、個別に各プロットを分析します。油を含むプロットは、ポケットと呼ばれています。2つのポケットが隣接している場合、それらは同じ石油鉱床の一部です。石油鉱床は非常に大きくすることができ、多数のポケットが含まれていてもよいです。あなたの仕事は、石油鉱床がグリッドに含まれているどのように多くの異なった決定することです。
入力
入力ファイルは、1つの以上のグリッドが含まれています。各グリッドは、単一のスペースで区切られたmおよびnは、グリッド内の行と列の数を含む行から始まります。M = 0、入力の終了を知らせる場合。そうでない場合は、1 <= M <= 100、1 <= N <= 100この後、各(行末文字をカウントしない)n文字のm本のラインです。各文字は1つのプロットに対応し、「*」のいずれかである、油の不在、または「@」を表す、オイルポケットを表します。
出力
各グリッドのため、出力の異なる油沈着の数。彼らは水平、垂直、または斜めに隣接している場合、2つの異なるポケットが同じ石油鉱床の一部です。石油鉱床は100個の以上のポケットを含んでいます。
サンプル入力
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
サンプル出力
0
1
2
2
#include<iostream>
#include<cstdio>
using namespace std;
int m,n;
char map[105][105];
int dir[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
void dfs(int x,int y){
for(int i=0;i<8;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx>=0&&xx<m&&yy>=0&&yy<n){
if(map[xx][yy]=='@'){
map[xx][yy]='*';
dfs(xx,yy);
}
}
}
}
int main(){
while(scanf("%d%d",&m,&n)){
if(m==0&&n==0)break;
//getchar();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
//直接用cin的好处,可以无视'\n'也就是说cin无法输入换行符,但是getchar和scanf会输入换行符
cin>>map[i][j];
}
}
int sum=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(map[i][j]=='@'){
map[i][j]='*';
sum++;
dfs(i,j);
}
}
}
printf("%d\n",sum);
}
return 0;
}
同様のトピック
2番目の質問:HDU1312赤と黒
問題の説明
正方形のタイルで覆われた長方形の部屋には、があります。各タイルは、赤または黒のいずれかで着色されています。男は黒いタイルの上に立っています。タイルから、彼は4枚の隣接するタイルの1つに移動することができます。しかし、彼は、彼は黒いタイルの上にのみ移動することができ、赤瓦の上に移動することはできません。
彼は、上述の移動を繰り返すことで到達することができ、黒のタイルの数をカウントするプログラムを書きます。
入力
入力は複数のデータセットから成ります。データセットは、2つの正の整数W及びHを含む行から始まります。W及びHは、それぞれ、xおよびy方向のタイルの数です。WとHは20以上ではありません。
W文字を含む各々がデータセットにおけるH複数のラインがあります。次のように各文字は、タイルの色を表しています。
'' -黒のタイル
「#」 -赤いタイル
「@」 -黒いタイルの上の男(データセットに正確に一度だけ表示されます)
出力
各データセットの場合は、あなたのプログラムは、彼が最初のタイルから到達可能なタイルの数が含まれている行の出力を(自身を含む)する必要があります。
サンプル入力
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
サンプル出力
45
59
6
13
ACcode
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int w,h;
int s_x,s_y;
int total=0;
char map[22][22];
char vis[22][22];
int dir[4][2]={0,1,0,-1,1,0,-1,0};
void dfs(int x,int y){
for(int i=0;i<4;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx>=0&&xx<h&&yy>=0&&yy<w&&map[xx][yy]=='.'&&vis[xx][yy]==0){
total++;
vis[xx][yy]=1;
dfs(xx,yy);
}
}
}
int main(){
while(scanf("%d %d",&w,&h)){
if(w==0&&h==0)break;
total=0;
getchar();
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
scanf("%c",&map[i][j]);
if(map[i][j]=='@'){s_x=i;s_y=j;map[i][j]='.';}
vis[i][j]=0;
}
getchar();
}
vis[s_x][s_y]=1;
total++;
dfs(s_x,s_y);
printf("%d\n",total);
}
return 0;
}
//不给初始点加访问标记的话,如果只有@一个点,直接走出去,为0
//所有这些都得先标记,避免当数很小的时候直接走出去而不进行计数自增操作
//也可以直接在dfs函数的第一行进行x,y访问标记。
3番目の質問
剪定1パリティ
の非常にシンプルなコンセプト
のエンドポイントは、EX、EYの座標;で設定された開始点は、BXを座標
最短経路は、ABS(BX-EX)+ ABSである (バイEY)
が、我々が見ることができる、それが明確です、それは偶数への我々の道のステップの最短数よりも、より確実に、歩いているかどうかを
十分最短経路奇数よりもタイトル入力のステップ数ならば、我々は行くことはありません:そう、単純化する最初のポイント直接出力Noに、
2剪定パスが
一旦NO見出されていない必要なエンドポイントに等しいステップの数及びDFSの現在のプロセスで大規模なもの、直接出力よりも大きいです
&計算、
nが奇数の場合、N 1およびN 2が剰余をとることと等価であるのは、答えは1であります
問題の説明
犬は彼に多くを魅了古代の迷路、中骨を発見しました。彼はそれを拾ったときしかし、迷路を振るようになった、と犬は地面が沈んで感じることができました。彼は骨が罠だったことに気づき、彼はこの迷路から抜け出すために必死に試みました。
迷路は、迷路内のドアがあったM.によるサイズのNの長方形でした。初めに、ドアを閉じ、それは時間の短い期間のためにT番目秒(1秒未満)で開くことになります。従って犬は正確にT番目の第二のドアに到達しなければなりませんでした。毎秒では、彼は、上、下、左と右の隣接ブロックのいずれかに1つのブロックを移動することができます。彼はブロックに入った後は、このブロックの地面が沈むと、次の秒で消えて起動します。彼は1秒以上1つのブロックに滞在できなかった、また彼が訪れたブロックに移動することができます。貧しい犬は生き残れますか?彼を助けてください。
入力
入力は複数のテストケースから構成されています。迷路のサイズとドアが開かれた時刻を示し、それぞれ、各テストケースの最初の行は三つの整数N、M、およびT(0 <T <50 1 <N、M <7)を含有します。次のNラインは、Mの文字を含む各ラインで、迷路のレイアウトを与えます。文字は、次のいずれかです。
「X」:犬は入ることができない壁のブロック;
「S」:犬の開始点;
「D」:ドア。または
「」:空のブロック。
入力は3つの0で終了します。このテストケースでは、処理されるべきではありません。
出力
犬がそうでなければ「NO」生存、またはできれば、各テストケースのために、一列「YES」で印刷します。
サンプル入力
4 4 5
SX
..X。
..XD
....
3 4 5
SX
..X。
... D
0 0 0
サンプル出力
NO
YES
DFSのではなく、BFSでは、間違いなく、最短パスでなければなりませんが、問題は時間にちょうど必要とステップの数ですが、BFSはこれを行うことはできません。
DFSとそう
ACcode
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
char maze[8][8];
int ma[8][8];
int s_x,s_y,e_x,e_y;
int n,m,t;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int flag=0;
int wall=0;
void dfs(int x,int y,int step){
if(step==t&&e_x==x&&e_y==y){
flag=1;
return;
}
if(flag){
return;
}
if(step>t){
return;
}
//奇偶剪枝,目前所在的点到终点的距离与当前已走的点减去时间点比较
int temp=abs(x-e_x)+abs(y-e_y)-abs(step-t);
//如果是一个奇数,或者当要走的路大于应该走的步数的时候return
if(temp>0||temp%2)return;
//temp&1表示判断是偶数还是奇数
for(int i=0;i<4;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&ma[xx][yy]==1){
ma[xx][yy]=0;
dfs(xx,yy,step+1);
//回溯!!!
ma[xx][yy]=1;
}
}
//
}
int main(){
while(cin>>n>>m>>t,(m+n+t)!=0){
//注意初始
wall=0;
flag=0;
getchar();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
char z;
scanf("%c",&z);
if(z=='.'){
ma[i][j]=1;
}else if(z=='S'){
ma[i][j]=1;
s_x=i,s_y=j;
}else if(z=='D'){
ma[i][j]=1;
e_x=i,e_y=j;
}else{
ma[i][j]=0;
wall++;
}
}
getchar();
}
//注意初始
ma[s_x][s_y]=0;
dfs(s_x,s_y,0);
//输入问题,当输入的条件不可执行的时候输出no
if(m*n-wall<t){
printf("NO\n");
}else{
if(flag==1){
printf("YES\n");
}else{
printf("NO\n");
}
}
}
return 0;
}