原题中文题面说的很清楚,这里就不转述了
1.选一个萝卜i做起点,求最小距离Ai和最小距离方案数Bi。
2.求覆盖所有萝卜,以洞为终点的路径条数Ci。
答案方案数就是
∑
i
=
1
n
B
i
∗
C
i
∗
[
A
i
=
=
m
i
n
A
]
\sum_{i=1}^nB_i*C_i*[Ai == minA]
∑i=1nBi∗Ci∗[Ai==minA]
注意
A
i
,
B
i
A_i,B_i
Ai,Bi在统计路径时路径不能跨过#和O
另外没有萝卜的情况不能输出-1.
然后独立插头的讨论需要格外注意。
AC Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define LL long long
#define maxn 10
#define inf 0x3f3f3f3f
#define mod 1000000007
using namespace std;
int n,m,mask[maxn],dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}},tx,ty;
int dis[maxn][maxn],wds[maxn][maxn];
char mp[maxn][maxn];
map<LL,pair<LL,LL> >st[2];
LL encode(int pos)
{ LL ret=0;
static int id[maxn]={},cnt;
memset(id,-1,sizeof id),cnt=id[2]=2,id[1]=1,id[0]=0;
for(int i=pos;i>=0;i--) ret=ret<<4|(id[mask[i]]==-1?id[mask[i]]=++cnt:id[mask[i]]);
if(pos == m-1) ret<<=4;
return ret;}
void decode(LL ret){ for(int i=0;i<=m;i++) mask[i]=ret&15,ret>>=4; }
void check2(pair<LL,LL>&a,pair<LL,LL>b)
{ if(a.first > b.first) a=b;
else if(a.first==b.first) a.second=(a.second+b.second)%mod;}
void check(int now,LL key,pair<LL,LL>b)
{ if(!b.second) return;
if(st[now].count(key)) check2(st[now][key],b);
else st[now][key]=b;}
inline bool ck(int x,int y){ return mp[x][y]=='#'||mp[x][y]=='O'; }
void dp(int i,int j,int now)
{
for(map<LL,pair<LL,LL> >::iterator it=st[now^1].begin();it!=st[now^1].end();it++)
{ decode((*it).first);pair<LL,LL>val=(*it).second;
if(mp[i][j] == '.' || mp[i][j] =='X' )
{
check(now,encode(j==m?m-1:m),val);
continue;
}
int L=mask[j-1],U=mask[j];
if(!L && !U)
{
if(ck(i,j+1) && ck(i+1,j))
mask[j-1] = mask[j] = 9 , check(now,encode(j==m?m-1:m),val);
if(dis[i][j] < inf && mp[i][j]=='#')
{
if(ck(i,j+1)) mask[j]=1,mask[j-1]=0,check(now,encode(j==m?m-1:m),make_pair(dis[i][j],1ll*val.second*wds[i][j]%mod));
if(ck(i+1,j)) mask[j]=0,mask[j-1]=1,check(now,encode(j==m?m-1:m),make_pair(dis[i][j],1ll*val.second*wds[i][j]%mod));
}
if(mp[i][j] == 'O')
{
if(ck(i,j+1)) mask[j]=2,mask[j-1]=0,check(now,encode(j==m?m-1:m),val);
if(ck(i+1,j)) mask[j]=0,mask[j-1]=2,check(now,encode(j==m?m-1:m),val);
}
}
else if(L && U)
{
if(L == U || (L<=2 && U<=2 && (i!=tx||j!=ty))) continue;
int tmp = min(L,U) , res = max(L,U);
for(int k=0;k<=m;k++)
if(mask[k] == res)
mask[k] = tmp;
mask[j-1] = mask[j] = 0;
check(now,encode(j==m?m-1:m),val);
}
else
{
mask[j] = U+L , mask[j-1] = 0;
if(ck(i,j+1)) check(now,encode(j==m?m-1:m),val);
mask[j-1] = U+L , mask[j] = 0;
if(ck(i+1,j)) check(now,encode(j==m?m-1:m),val);
int tmp = U+L;
if(tmp == 1 && mp[i][j] == 'O') mask[j-1]=mask[j]=0,check(now,encode(j==m?m-1:m),val);
if(tmp == 2 && (dis[i][j] < inf && mp[i][j]=='#'))
mask[j-1]=mask[j]=0,check(now,encode(j==m?m-1:m),make_pair(dis[i][j],1ll*val.second*wds[i][j]%mod));
if(tmp > 2)
{
if(mp[i][j] == 'O')
{
for(int k=0;k<=n;k++)
if(mask[k] == tmp)
mask[k] = 2;
mask[j-1] = mask[j] = 0;
check(now,encode(j==m?m-1:m),val);
}
if(dis[i][j] < inf && mp[i][j] == '#')
{
decode((*it).first);
for(int k=0;k<=n;k++)
if(mask[k] == tmp)
mask[k] = 1;
mask[j-1] = mask[j] = 0;
check(now,encode(j==m?m-1:m),make_pair(dis[i][j],1ll*val.second*wds[i][j]%mod));
}
}
}
}
}
int main()
{
int T;scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
scanf("%d%d",&n,&m);
memset(mp,0,sizeof mp);
for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
queue<pair<int,int> >q;
memset(dis,0x3f,sizeof dis);
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(mp[i][j] == 'X') q.push(make_pair(i,j)),dis[i][j]=0;
if(mp[i][j] == '#' || mp[i][j] == 'O')
cnt++,tx=i,ty=j;
}
queue<pair<int,int> >q2;
for(int x,y;!q.empty();)
{
x=q.front().first,y=q.front().second,q.pop();
q2.push(make_pair(x,y));
if(mp[x][y] == '#' || mp[x][y] == 'O')
{
continue;
}
for(int i=0;i<4;i++)
{
int u = dir[i][0] + x, v = dir[i][1] + y;
if(u > 0 && u <= n && v > 0 && v <= m && dis[u][v] > dis[x][y] + 1)
{
dis[u][v] = dis[x][y] + 1;
q.push(make_pair(u,v));
}
}
}
memset(wds,0,sizeof wds);
wds[q2.front().first][q2.front().second] = 1;
q2.pop();
for(int x,y;!q2.empty();)
{
x=q2.front().first,y=q2.front().second,q2.pop();
for(int i=0;i<4;i++)
{
int u = dir[i][0] + x, v = dir[i][1] + y;
if(u > 0 && u <= n && v > 0 && v <= m && dis[u][v] == dis[x][y] - 1 && (mp[u][v]=='.' || mp[u][v]=='X'))
{
wds[x][y] = (wds[x][y] + wds[u][v]) % mod;
}
}
}
int now = 1;
st[0].clear(),st[0][0]=make_pair(inf,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
st[now].clear();
dp(i,j,now);
now^=1;
}
if(cnt == 1) printf("Case #%d: %d %d\n",cas,dis[tx][ty],wds[tx][ty]);
else if(st[now^1].count(0)) printf("Case #%d: %I64d %I64d\n",cas,st[now^1][0].first+cnt-1,((st[now^1][0].second%mod)+mod)%mod);
else printf("Case #%d: -1\n",cas);
}
}