HDU CakeMan
D是卖蛋糕的,S是卖蛋糕的人的家,C是城管的家。D要回家按最短路回家,而C要从最短路的必经之路逮住他,求C到D回家的必经之路的最短距离。
知识点:求最短路必经点,将最短路找出来,然后dp_s[i][j]为到S点的路径数量,dp_d[i][j]为到D点的路径数量,sum为S点到D点的路径数量,如果dp_s[i][j]*dp_d[i][j]=sum的话那么点(i,j)就是最短路必经点。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
char map[110][110];
int dis_d[110][110],dis_s[110][110],dis_c[110][110];
int dp_d[110][110],dp_s[110][110];
bool have[110][110],have_c[110][110];
int edge[110][110];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int n,m;
struct skt{
int x,y;
int dis;
friend bool operator <(skt a,skt b){
return a.dis>b.dis;
}
};
bool can(int x,int y){
if(x>=1&&x<=n&&y>=1&&y<=m&&map[x][y]!='X')
return true;
return false;
}
void bfs_s(int x,int y){
int i;
memset(have,0,sizeof(have));
priority_queue<skt>q;
skt s;
s.x=x;s.y=y;s.dis=0;
q.push(s);
have[x][y]=true;
while(!q.empty()){
skt t=q.top();
q.pop();
for(i=0;i<4;i++){
int tx=t.x+dx[i];
int ty=t.y+dy[i];
if(!can(tx,ty)||have[tx][ty])
continue;
int op=1;
have[tx][ty]=true;
if(map[tx][ty]>='0'&&map[tx][ty]<='9')
op+=map[tx][ty]-'0';
dis_s[tx][ty]=t.dis+1;
skt k;
k.dis=t.dis+op;
k.x=tx;k.y=ty;
q.push(k);
}
}
}
void bfs_d(int x,int y){
int i;
memset(have,0,sizeof(have));
priority_queue<skt>q;
skt s;
s.x=x;s.y=y;s.dis=0;
q.push(s);
have[x][y]=true;
while(!q.empty()){
skt t=q.top();
q.pop();
for(i=0;i<4;i++){
int tx=t.x+dx[i];
int ty=t.y+dy[i];
if(!can(tx,ty)||have[tx][ty])
continue;
int op=1;
have[tx][ty]=true;
if(map[tx][ty]>='0'&&map[tx][ty]<='9')
op+=map[tx][ty]-'0';
dis_d[tx][ty]=t.dis+op;
skt k;
k.dis=t.dis+op;
k.x=tx;k.y=ty;
q.push(k);
}
}
}
void bfs_c(int x,int y){
int i;
priority_queue<skt>q;
skt s;
s.x=x;s.y=y;s.dis=0;
q.push(s);
have_c[x][y]=true;
while(!q.empty()){
skt t=q.top();
q.pop();
for(i=0;i<4;i++){
int tx=t.x+dx[i];
int ty=t.y+dy[i];
if(!can(tx,ty)||have_c[tx][ty])
continue;
have_c[tx][ty]=true;
dis_c[tx][ty]=t.dis+1;
skt k;
k.dis=dis_c[tx][ty];
k.x=tx;k.y=ty;
q.push(k);
}
}
}
void dfs_d(int x,int y){
int i;
memset(have,0,sizeof(have));
priority_queue<skt>q;
skt s;
s.x=x;s.y=y;
q.push(s);
dp_d[x][y]=1;
have[x][y]=true;
while(!q.empty()){
skt t=q.top();
q.pop();
for(i=0;i<4;i++){
int tx=t.x+dx[i];
int ty=t.y+dy[i];
if(!can(tx,ty)||!edge[tx][ty])
continue;
int op=1;
//cout<<tx<<" "<<ty<<"h1\n";
if(map[tx][ty]>='0'&&map[tx][ty]<='9')
op+=map[tx][ty]-'0';
//cout<<tx<<" "<<ty<<"h2\n";
if(dis_d[t.x][t.y]+op==dis_d[tx][ty]){
dp_d[tx][ty]+=dp_d[t.x][t.y];
}
if(!have[tx][ty]){
have[tx][ty]=true;
skt k;
k.x=tx;k.y=ty;
k.dis=dis_d[tx][ty];
q.push(k);
}
}
}
}
void dfs_s(int x,int y){
int i;
memset(have,0,sizeof(have));
priority_queue<skt>q;
skt s;
s.x=x;s.y=y;
q.push(s);
dp_s[x][y]=1;
have[x][y]=true;
while(!q.empty()){
skt t=q.top();
q.pop();
for(i=0;i<4;i++){
int tx=t.x+dx[i];
int ty=t.y+dy[i];
if(!can(tx,ty)||!edge[tx][ty])
continue;
//cout<<tx<<" "<<ty<<"\n";
int op=1;
if(map[t.x][t.y]>='0'&&map[t.x][t.y]<='9')
op+=map[t.x][t.y]-'0';
if(dis_s[t.x][t.y]+op==dis_s[tx][ty]){
dp_s[tx][ty]+=dp_s[t.x][t.y];
}
if(!have[tx][ty]){
have[tx][ty]=true;
skt k;
k.x=tx;k.y=ty;
op=0;
if(map[tx][ty]>='0'&&map[tx][ty]<='9')
op+=map[tx][ty]-'0';
k.dis=dis_s[tx][ty]+op;
q.push(k);
}
}
}
}
int main(void){
int T,i,j,sx,sy,dx,dy,cx,cy;
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
memset(edge,0,sizeof(edge));
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
have_c[i][j]=false;
dp_s[i][j]=0;
dp_d[i][j]=0;
dis_s[i][j]=0;
dis_d[i][j]=0;
dis_c[i][j]=0;
}
}
for(i=1;i<=n;i++){
scanf("%s",map[i]+1);
}
//cout<<map[3][5]<<"\n";
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(map[i][j]=='S'){
bfs_s(i,j);
sx=i;sy=j;
}
else if(map[i][j]=='D'){
bfs_d(i,j);
dx=i;dy=j;
}
else if(map[i][j]=='C'){
bfs_c(i,j);
cx=i;cy=j;
}
}
}
int ans=INF;
int len=dis_d[sx][sy];
edge[sx][sy]=edge[dx][dy]=1;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if((i==sx&&j==sy)||(i==dx&&j==dy))
continue;
if(dis_d[i][j]+dis_s[i][j]==len){
edge[i][j]=1;
//cout<<i<<" "<<j<<"\n";
}
}
}
dfs_d(dx,dy);
dfs_s(sx,sy);
int sum=dp_d[sx][sy];
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if((i==sx&&j==sy)||(i==dx&&j==dy))
continue;
//cout<<dp_d[i][j]<<" "<<dp_s[i][j]<<"\n";
if(dp_d[i][j]*dp_s[i][j]==sum){
//cout<<i<<" "<<j<<"\n";
if(have_c[i][j]){
ans=min(ans,dis_c[i][j]);
}
}
}
}
if(ans==INF)
cout<<"-1\n";
else
cout<<ans<<"\n";
}
return 0;
}