kuangbin在vjudge上面挂了一些专题,感谢bin神带我飞~
Problem APOJ1321
中文题目 DFS 注意某一行可以不放棋子,因此需要在DFS函数后面加一个dfs(row+1,num)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
int visit[10],tot,n,k;
int ch[10][10];
void dfs(int row,int num)
{
int j;
if(num==k)
{
tot++;
return;
}
if(row>n)
return;
for(j=1;j<=n;j++)
if(ch[row][j]&&!visit[j])
{
visit[j]=1;
dfs(row+1,num+1);
visit[j]=0;
}
dfs(row+1,num);
return;
}
int main()
{
int i,j;
char x;
while(scanf("%d%d",&n,&k)!=EOF&&(n!=-1||k!=-1))
{
getchar();
memset(ch,0,sizeof(ch));
memset(visit,0,sizeof(visit));
tot=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%c",&x);
if(x=='#')
ch[i][j]=1;
if(j==n)
getchar();
}
dfs(1,0);
printf("%d\n",tot);
}
return 0;
}
Problem B
POJ2251
三维的,共有6个方向,BFS,很水
#include <iostream>
#include <queue>
#include <cstring>
#include<cstdio>
using namespace std;
int l,r,c;
char g[31][31][31];
int shift[6][3]={{-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1}};
short flag[31][31][31];
int s[3];
int e[3];
int min_path=0xffff;
struct Point
{
int x;
int y;
int z;
int step;
};
queue<Point> mq;
bool inrange(int x,int y,int z)
{
if(x>=0 && x<l && y>=0 && y<r && z>=0 && z<c)
return true;
else
return false;
}
void bfs(int x,int y,int z)
{
Point p;
p.x=x;
p.y=y;
p.z=z;
p.step=0;
flag[x][y][z]=1;
mq.push(p);
while(!mq.empty())
{
Point q = mq.front();
mq.pop();
if(q.x==e[0] && q.y==e[1] && q.z==e[2])
{
min_path = q.step;
return;
}
for(int i=0;i<6;i++)
{
Point m;
m.x= q.x+shift[i][0];
m.y= q.y+shift[i][1];
m.z= q.z+shift[i][2];
m.step =q.step+1;
if(inrange(m.x,m.y,m.z) && g[m.x][m.y][m.z]!='#' && flag[m.x][m.y][m.z]==0)
{
flag[m.x][m.y][m.z]=1;
mq.push(m);
}
}
}
}
int main()
{
cin>>l;
cin>>r;
cin>>c;
int i,j,k;
while(l || r || c)
{
min_path=0xffff;
memset(g,0,sizeof(g));
memset(flag,0,sizeof(flag));
while(!mq.empty())
{
mq.pop();
}
for(i=0;i<l;i++)
{
for(j=0;j<r;j++)
{
getchar();
for(k=0;k<c;k++)
{
g[i][j][k]=getchar();
if(g[i][j][k]=='S')
{
s[0]=i;
s[1]=j;
s[2]=k;
}
if(g[i][j][k]=='E')
{
e[0]=i;
e[1]=j;
e[2]=k;
}
}
}
getchar();
}
bfs(s[0],s[1],s[2]);
if(min_path<0xffff)
cout<<"Escaped in "<<min_path<<" minute(s)."<<endl;
else
cout<<"Trapped!"<<endl;
cin>>l;
cin>>r;
cin>>c;
}
}
Problem C
POJ3278
BFS水题 n经过多次+1or-1or*2后得到n
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int n,k,ans;
int visit[200005];
struct pos
{
int x;
int t;
};
queue<pos>s;
void bfs(int x)
{
pos b;
b.x=x;
b.t=0;
visit[x]=1;
s.push(b);
while(!s.empty())
{
pos m=s.front();
s.pop();
if(m.x==k)
{
ans=m.t;
return;
}
pos q;
q.x=m.x-1;
q.t=m.t+1;
if(q.x>=0&&q.x<=100000&&visit[q.x]==0)
{
visit[q.x]=1;
s.push(q);
}
q.x=m.x+1;
q.t=m.t+1;
if(q.x>=0&&q.x<=100000&&visit[q.x]==0)
{
visit[q.x]=1;
s.push(q);
}
q.x=m.x*2;
q.t=m.t+1;
if(q.x>=0&&q.x<=100000&&visit[q.x]==0)
{
visit[q.x]=1;
s.push(q);
}
}
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
memset(visit,0,sizeof(visit));
while(!s.empty())
s.pop();
bfs(n);
printf("%d\n",ans);
}
return 0;
}
Problem D
POJ3279
翻白块,开始想了好久,枚举第一行,后面的状态就可以确定了,因为上面一行没有翻过来的白块只有通过下一行才能翻过来
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define INF 0x7fffffff
using namespace std;
int n,m,mint;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int map[16][16],t[16][16],ans[16][16],op[16][16];
void operate(int x,int y)
{
op[x][y]=1;
t[x][y]^=1;
for(int k=0;k<4;k++)
{
int nowx=x+dir_x[k];
int nowy=y+dir_y[k];
if(nowx<1||nowy<1||nowx>n||nowy>m)
continue;
t[nowx][nowy]^=1;
}
}
void solve(int x)
{
int tot=0;
memset(op,0,sizeof(op));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
t[i][j]=map[i][j];
for(int i=1;i<=m;i++)
if((1<<(i-1))&x)
{
tot++;
if(tot>=mint)
return;
operate(1,m-i+1);
}
for(int i=2;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(t[i-1][j])
{
tot++;
if(tot>=mint)
return;
operate(i,j);
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(t[i][j])
return;
mint=tot;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans[i][j]=op[i][j];
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&map[i][j]);
mint=INF-10;
for(i=0;i<=((1<<m)-1);i++)
solve(i);
if(mint!=INF-10)
{
for(i=1;i<=n;i++)
{
for(j=1;j<m;j++)
printf("%d ",ans[i][j]);
printf("%d\n",ans[i][m]);
}
}
else printf("IMPOSSIBLE\n");
}
return 0;
}
Problem E
POJ1426
一开始想的很复杂。。。后来发现只是个简单的DFS
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
bool found;
void DFS(unsigned __int64 t ,int n,int k)
{
if(found)
return ;//如果已经发现了答案就没搜的必要了
if(t%n==0)
{//发现答案,输出,标记变量该true
printf("%I64u\n",t);
found=true;
return ;
}
if(k==19)//到第19层,回溯
return ;
DFS(t*10,n,k+1); //搜索×10
DFS(t*10+1,n,k+1); //搜索×10+1
}
int main()
{
int n;
while(cin>>n,n)
{
found=false;//标记变量,当为true代表搜到了题意第一的m
DFS(1,n,0); //从1开始搜n的倍数,第三个参数代表搜的层数,当到第19层时返回(因为第20层64位整数存不下)
}
return 0;
}
Problem F
POJ3126
素数打表DFS搞定
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
int f[10000],prime[10000],visit[10000];
int x,tag;
struct state
{
int w[4];
int t;
};
void isprime()
{
memset(prime,0,sizeof(prime));
memset(f,0,sizeof(f));
for(int i=2;i<=9999;i++)
{
if(f[i]==0)
{
for(int j=i+i;j<=9999;j+=i)
f[j]=1;
prime[i]=1;
}
}
}
void bfs()
{
int i,j;
queue<state>s;
state p;
p.w[0]=x/1000;
p.w[1]=(x-p.w[0]*1000)/100;
p.w[3]=x%10;
p.w[2]=(x-1000*p.w[0]-100*p.w[1]-p.w[3])/10;
p.t=0;
s.push(p);
memset(visit,0,sizeof(visit));
visit[x]=1;
while(!s.empty())
{
state q,n;
q=s.front();
s.pop();
int now=q.w[0]*1000+q.w[1]*100+q.w[2]*10+q.w[3];
// printf("%d\n",now);
// getchar();
if(now==tag)
{
printf("%d\n",q.t);
return;
}
for(i=0;i<=3;i++)
for(j=0;j<=9;j++)
{
n=q;
n.w[i]=j;
n.t=q.t+1;
int sum=n.w[0]*1000+n.w[1]*100+n.w[2]*10+n.w[3];
if(!visit[sum]&&prime[sum]&&sum>1000)
{
// printf("%d\n",sum);
s.push(n);
visit[sum]=1;
}
}
}
printf("Impossible\n");
}
int main()
{
int t,i;
isprime();
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
scanf("%d%d",&x,&tag);
bfs();
}
}
return 0;
}
Problem G
POJ3087
模拟,如果回到初态说明不能成功,看到了一个特别短的代码,拿来引用了,很简洁,一看便懂
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int i,n,t,j,m,k;
char s1[201],s2[201],s[201],s0[201],stag[401];
while(scanf("%d",&m)!=EOF)
{
for(k=1;k<=m;k++)
{
scanf("%d",&n);
scanf("%s%s%s",s1,s2,stag);
strcpy(s,s1);
strcat(s,s2);
strcpy(s0,s);
for(t=0;strcmp(s,stag)!=0;t++)
{
for(j=0;j<n;j++)
s1[j]=s[j];
for(i=0;i<n;i++,j++)
s2[i]=s[j];
for(i=0,j=0;i<n;i++,j+=2)
{
s[j]=s2[i];
s[j+1]=s1[i];
}
if(strcmp(s0,s)==0)
{
t=-1;
break;
}
}
printf("%d %d\n",k,t);
}
}
return 0;
}
Problem H
POJ3414
DFS六种可能性,用数组保存每次的操作代号最后输出,一开始用string直接保存的,结果TLE了。。。
#include<string>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,c,res;
char pa[10010],pp[10010];
bool flag,vis[105][105];
void dfs(int x,int y,int dep)
{
if(dep>res)
return;
if(x==c||y==c)
{
if(dep<res)
{
flag=1;
res=dep;
for(int i=0;i<res;i++)
pa[i]=pp[i];
}
return;
}
if(x<a&&!vis[a][y])//FILL 1
{
vis[a][y]=1;
pp[dep]='f';
dfs(a,y,dep+1);
vis[a][y]=0;
}
if(y<b&&!vis[x][b])//FILL 2
{
vis[x][b]=1;
pp[dep]='F';
dfs(x,b,dep+1);
vis[x][b]=0;
}
if(x>0&&!vis[0][y])//DROP 1
{
vis[0][y]=1;
pp[dep]='d';
dfs(0,y,dep+1);
vis[0][y]=0;
}
if(y>0&&!vis[x][0])//DROP 2
{
vis[x][0]=1;
pp[dep]='D';
dfs(x,0,dep+1);
vis[x][0]=0;
}
if(x>0&&y<b)//POUR(1,2)
{
int t=min(x,b-y);
if(!vis[x-t][y+t])
{
vis[x-t][y+t]=1;
pp[dep]='p';
dfs(x-t,y+t,dep+1);
vis[x-t][y+t]=0;
}
}
if(y>0&&x<a)//POUR(2,1)
{
int t=min(y,a-x);
if(!vis[x+t][y-t])
{
vis[x+t][y-t]=1;
pp[dep]='P';
dfs(x+t,y-t,dep+1);
vis[x+t][y-t]=0;
}
}
return;
}
int main()
{
int i;
while(scanf("%d%d%d",&a,&b,&c)!=EOF)
{
memset(vis,0,sizeof(vis));
vis[0][0]=1;
flag=0;
res=0x7fffffff;
dfs(0,0,0);
if(flag)
{
printf("%d\n",res);
for(int i=0;i<res;i++)
{
if(pa[i]=='f')
printf("FILL(1)\n");
if(pa[i]=='F')
printf("FILL(2)\n");
if(pa[i]=='d')
printf("DROP(1)\n");
if(pa[i]=='D')
printf("DROP(2)\n");
if(pa[i]=='p')
printf("POUR(1,2)\n");
if(pa[i]=='P')
printf("POUR(2,1)\n");
}
}
else printf("impossible\n");
}
return 0;
}
Problem I
FZU2150
从两个地方放火,两处可以是同一地点,问最短需要多少时间才能让他们玩上XXOO游戏(可见 福州大学的Acmer啧啧啧啧)。。。。。。。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 0x7fffffff
using namespace std;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int n,m,tmin,tmax;
int map[11][11],vis[11][11];
int visit[11][11][11][11];
struct state
{
int x,y;
int t;//time
};
int inrange(int x,int y)
{
if(x<1||x>n||y<1||y>m)
return 1;
return 0;
}
void bfs(int x1,int y1,int x2,int y2)
{
queue<state>s;
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
vis[i][j]=map[i][j];
state p;
p.x=x1;
p.y=y1;
p.t=0;
s.push(p);
p.x=x2;
p.y=y2;
p.t=0;
s.push(p);
vis[x1][y1]=vis[x2][y2]=0;
while(!s.empty())
{
state q;
q=s.front();
s.pop();
tmax=q.t;
for(i=0;i<4;i++)
{
state now;
now.x=q.x+dir_x[i];
now.y=q.y+dir_y[i];
now.t=q.t+1;
if(!inrange(now.x,now.y)&&vis[now.x][now.y])
{
vis[now.x][now.y]=0;
s.push(now);
}
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(vis[i][j])
tmax=INF;
}
}
int main()
{
int i,j,t,p,q,k;
char c;
while(scanf("%d",&t)!=EOF)
{
for(k=1;k<=t;k++)
{
scanf("%d%d",&n,&m);
getchar();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>c;
if(c=='#')
map[i][j]=1;
else
map[i][j]=0;
}
}
tmin=INF;
memset(visit,0,sizeof(visit));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
for(p=1;p<=n;p++)
for(q=1;q<=m;q++)
{
if(map[i][j]&&map[p][q]&&!visit[p][q][i][j])
{
visit[i][j][p][q]=1;
bfs(i,j,p,q);
tmin=min(tmin,tmax);
}
}
if(tmin==INF)
printf("Case %d: -1\n",k);
else
printf("Case %d: %d\n",k,tmin);
}
}
return 0;
}
Problem J
UVA11624
先BFS一次每一块着火的最段时间,再对JOE进行一次BFS,如果JOE到达某块的时间比它的着火时间短加入队列,
注意初始着火点可能有多个
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#define INF 0x7fffffff-10
using namespace std;
int dir_x[4]={1,-1,0,0};
int dir_y[4]={0,0,1,-1};
int c,r,fx[1000005],fy[1000005],jx,jy,cnt;
int tim[1005][1005];
bool vis[1005][1005];
bool map[1005][1005];
struct state
{
int x,y;
int t;
};
int inrange(int x,int y)
{
if(x>r||x<1||y>c||y<1)
return 0;
return 1;
}
void Fbfs()
{
int i,j;
queue<state>s;
state p;
memset(vis,0,sizeof(vis));
for(i=0;i<=cnt-1;i++)
{
p.x=fx[i];
p.y=fy[i];
p.t=0;
s.push(p);
vis[fx[i]][fy[i]]=1;
}
while(!s.empty())
{
p=s.front();
s.pop();
for(i=0;i<4;i++)
{
state now;
now.x=p.x+dir_x[i];
now.y=p.y+dir_y[i];
if(inrange(now.x,now.y)&&!vis[now.x][now.y]&&!map[now.x][now.y]&&tim[now.x][now.y]>p.t+1)
{
vis[now.x][now.y]=1;
// if(time[now.x][now.y]>now.t)
now.t=p.t+1;
tim[now.x][now.y]=now.t;
s.push(now);
}
}
}
}
void Jbfs()
{
int i,j;
state p;
queue<state>s;
p.x=jx;
p.y=jy;
p.t=0;
s.push(p);
memset(vis,0,sizeof(vis));
vis[jx][jy]=1;
while(!s.empty())
{
p=s.front();
s.pop();
if(p.x==r||p.y==c||p.x==1||p.y==1)
{
printf("%d\n",p.t+1);
return;
}
for(i=0;i<4;i++)
{
state now;
now.x=p.x+dir_x[i];
now.y=p.y+dir_y[i];
now.t=p.t+1;
if(now.t<tim[now.x][now.y]&&!vis[now.x][now.y]&&inrange(now.x,now.y)&&!map[now.x][now.y])
{
vis[now.x][now.y]=1;
s.push(now);
}
}
}
printf("IMPOSSIBLE\n");
}
int main()
{
int n,i,j;
char ch;
while(scanf("%d",&n)!=EOF)
{
while(n--)
{
cnt=0;
scanf("%d%d",&r,&c);
for(i=1;i<=r;i++)
for(j=1;j<=c;j++)
{
cin>>ch;
tim[i][j]=INF;
if(ch=='J')
{
jx=i;
jy=j;
map[i][j]=0;
}
if(ch=='F')
{
fx[cnt]=i;
fy[cnt++]=j;
map[i][j]=1;
tim[i][j]=0;
}
if(ch=='#')
map[i][j]=1;
if(ch=='.')
map[i][j]=0;
}
Fbfs();
Jbfs();
}
}
return 0;
}
Problem K
POJ3984
结构体中用,pre变量保存当前点之前的位置,用数组模拟队列
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
int visit[6][6];
struct point
{
int x,y;
int pre;//记录之前的位置 pre=previous
}queue[100];
bool inrange(int x,int y)
{
if(x>4||x<0||y>4||y<0)
return false;
return true;
}
void print(int i)
{
if(queue[i].pre!=-1)
{
print(queue[i].pre);
printf("(%d, %d)\n",queue[i].x,queue[i].y);
}
}
void bfs()
{
int a,b;
int front,rear;
front=0;
rear=1;
queue[front].x=0;
queue[front].y=0;
queue[front].pre=-1;//(0, 0)之前的位置记为-1
while(front<rear)
{
for(int i=0;i<=3;i++)
{
a=queue[front].x+dir_x[i];
b=queue[front].y+dir_y[i];
if(!inrange(a,b)||visit[a][b])
continue;
else
{
visit[a][b]=1;
queue[rear].x=a;
queue[rear].y=b;
queue[rear].pre=front;
rear++;
}
if(a==4&&b==4)
{
printf("(0, 0)\n");
print(front);
printf("(4, 4)\n");
}
}
front++;
}
}
int main()
{
int i,j;
while(scanf("%d",&visit[0][0])!=EOF)
{
memset(visit,0,sizeof(visit));
for(i=1;i<=4;i++)
scanf("%d",&visit[0][i]);
for(i=1;i<=4;i++)
for(j=0;j<=4;j++)
scanf("%d",&visit[i][j]);
bfs();
}
return 0;
}
Problem L
HDU1241
连通块问题,DFS解决
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int dir_x[8]={0,0,1,-1,1,1,-1,-1};
int dir_y[8]={1,-1,0,0,1,-1,1,-1};
int map[105][105];
int m,n;
void dfs(int x,int y)
{
map[x][y]=0;
for(int i=0;i<=7;i++)
{
int a=x+dir_x[i];
int b=y+dir_y[i];
if(a<1||b<1||b>n||a>m||map[a][b]==0)
continue;
else
dfs(a,b);
}
return;
}
int main()
{
int ans,i,j;
char c;
while(scanf("%d %d",&m,&n)!=EOF&&(m||n))
{
getchar();
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
cin>>c;
if(c=='@')
map[i][j]=1;
else
map[i][j]=0;
}
}
// for(i=1;i<=m;i++)
//{
// for(j=1;j<=n;j++)
// printf("%d",map[i][j]);
// printf("\n");
// }
ans=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
if(map[i][j])
{
dfs(i,j);
ans++;
}
printf("%d\n",ans);
}
return 0;
}
Problem M
HDU1495
倒可乐, 主要就是麻烦。。。分类讨论,结构体里每个变量都要赋值,找了好久的bug。。。
Problem N
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int visit[300][300];
int f[3];
struct state
{
int x[3];
int step;//倒的次数;
};
queue<state>s;
void bfs()
{
int i,j;
state p;
p.x[0]=f[0];
p.x[1]=0;
p.x[2]=0;
p.step=0;
s.push(p);
while(!s.empty())
{
state q;
q=s.front();
s.pop();
if((q.x[0]==f[0]/2&&q.x[1]==f[0]/2)||(q.x[0]==f[0]/2&&q.x[2]==f[0]/2)||(q.x[2]==f[0]/2&&q.x[1]==f[0]/2))//判断是否满足条件
{
printf("%d\n",q.step);
return;
}
for(i=0;i<=2;i++)
{
state y;
if(q.x[i]>0)//将i的可乐倒入j中
{
for(j=0;j<=2;j++)
{
if(i==j)
continue;
if(q.x[i]+q.x[j]>f[j])
{
y.x[i]=q.x[i]-(f[j]-q.x[j]);
y.x[j]=f[j];
y.x[3-i-j]=q.x[3-i-j];
}
else
{
y.x[i]=0;
y.x[j]=q.x[i]+q.x[j];
y.x[3-i-j]=q.x[3-i-j];
}
int a,b;
a=y.x[1];
b=y.x[2];
if(a>=0&&b>=0&&a<=f[1]&&b<=f[2]&&visit[a][b]==0)
{
visit[a][b]=1;
y.step=q.step+1;
s.push(y);
}
}
}
}
}
printf("NO\n");
}
int main()
{
while(scanf("%d%d%d",&f[0],&f[1],&f[2])!=EOF&&(f[0]||f[1]||f[2]))
{
if(f[0]%2)
{
printf("NO\n");
continue;
}
if(f[1]==f[2])
{
printf("1\n");
continue;
}
else
{
while(!s.empty())
s.pop();
memset(visit,0,sizeof(visit));
visit[0][0]=true;
bfs();
}
}
return 0;
}
Problem N
HDU2612
审题,两人时间的总和最少而不是俩人的时间只算一次,两次BFS即可,最后取最小时间的和
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define INF 0x7fffffff
using namespace std;
int dir_x[4]={0,0,1,-1};
int dir_y[4]={1,-1,0,0};
char map[205][205];
int ans1[205][205];
int ans2[205][205];
int visit[205][205];
int x1,x2,y1,y2,m,n,mint;
struct state
{
int x,y;
int step;
};
int inrange(int x,int y)
{
if(x<1||x>n||y<1||y>m)
return 0;
return 1;
}
void bfs(int x,int y,int ans[205][205])
{
int i,j;
memset(visit,0,sizeof(visit));
memset(ans,0,sizeof(ans));
queue<state>s;
state p;
p.x=x;
p.y=y;
p.step=0;
s.push(p);
visit[x][y]=1;
while(!s.empty())
{
state q;
q=s.front();
s.pop();
if(map[q.x][q.y]=='@')
{
ans[q.x][q.y]=q.step;
}
for(i=0;i<4;i++)
{
state w;
w.x=q.x+dir_x[i];
w.y=q.y+dir_y[i];
w.step=q.step+1;
if(inrange(w.x,w.y)&&!visit[w.x][w.y]&&map[w.x][w.y]!='#')
{
s.push(w);
visit[w.x][w.y]=1;
}
}
}
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
getchar();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='Y')
{
x1=i;
y1=j;
}
if(map[i][j]=='M')
{
x2=i;
y2=j;
}
}
}
bfs(x1,y1,ans1);
bfs(x2,y2,ans2);
mint=INF;
// for(i=1;i<=n;i++)
// {
// for(j=1;j<=m;j++)
// {
// cout<<ans2[i][j];
// }
// printf("\n");
// }
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(ans1[i][j]&&ans2[i][j]&&map[i][j]=='@')
mint=min(mint,ans1[i][j]+ans2[i][j]);
}
printf("%d\n",mint*11);
}
return 0;
}