题意(原谅我懒癌晚期)
分析:
第一次看错题目了…以为是路径总数…直接写spfa…后来发现是0的位置不同才叫方案不同…额…2333333333333
现在考虑我们所求的是0的位置不同的方案总数…
因为1的存在…我们无法直接得到当前路径上0的位置…所以说要想一种机智的办法来排除1的干扰…
第一想法是把1去掉…但是这样会导致一些合法的路径被断开…那怎么办…那就把因为去掉1而断开的边强行加上去一条权值为1的边…
所以我们就可以通过bfs找到每个0点和起点的能够花费1个代价到达的点…从而得到一张新的图,然后再这张图上跑最短路统计方案数即可…
但是在处理方案数目的时候我犯了一个zz的错误…我选择了dijkstra…其实可以统计…但是我妄想用一个”优美“的算法(一遍求出来)…然后就挂了…
代码如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define inf 0x3f3f3f3f
//by NeighThorn
using namespace std;
const int maxn=900+5,maxm=810000+5;
int n,m,mp[35][35],hd[maxn],to[maxm],vis[35][35],vi[maxn],nxt[maxm],cnt,stx,sty,enx,eny,mv[8][2]={1,2,-1,2,-1,-2,1,-2,2,1,-2,1,-2,-1,2,-1},dis[maxn];
long long num[maxn];
struct M{
int v,d;
M(int a=0,int b=0){
v=a,b=d;
}
friend bool operator < (M x,M y){
return x.d>y.d;
}
};
struct lala{
int x,y,step;
lala(int a=0,int b=0,int c=0){
x=a,y=b,step=c;
}
};
inline void add(int x,int y){
to[cnt]=y;
nxt[cnt]=hd[x];
hd[x]=cnt++;
}
inline void bfs(int X,int Y){
memset(vis,0,sizeof(vis));
queue<lala> q;
q.push(lala(X,Y,0)),vis[X][Y]=1;
while(!q.empty()){
int x=q.front().x,y=q.front().y,step=q.front().step;
q.pop();
for(int i=0;i<=7;i++){
int xx=x+mv[i][0],yy=y+mv[i][1];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&mp[xx][yy]!=2&&mp[xx][yy]!=3){
if(mp[xx][yy]==4&&step==0)
add((X-1)*m+Y,(xx-1)*m+yy),vis[xx][yy]=1;
else if(mp[xx][yy]==1&&step==0)
add((X-1)*m+Y,(xx-1)*m+yy),vis[xx][yy]=1;
else if(mp[xx][yy]==0&&step==0)
q.push(lala(xx,yy,step)),vis[xx][yy]=1;
}
}
}
}
inline void findsmallestlength(void){
queue<int> q;memset(dis,inf,sizeof(dis));memset(num,0,sizeof(num));memset(vi,0,sizeof(vi));
q.push((stx-1)*m+sty),vi[(stx-1)*m+sty]=1,dis[(stx-1)*m+sty]=-1,num[(stx-1)*m+sty]=1;
while(!q.empty()){
int top=q.front();q.pop();vi[top]=0;
for(int i=hd[top];i!=-1;i=nxt[i]){
if(dis[to[i]]>dis[top]+1){
dis[to[i]]=dis[top]+1,num[to[i]]=num[top];
if(!vi[to[i]])
q.push(to[i]),vi[to[i]]=1;
}
else if(dis[to[i]]==dis[top]+1){
num[to[i]]+=num[top];
if(!vi[to[i]])
q.push(to[i]),vi[to[i]]=1;
}
}
}
}
signed main(void){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]==3)
stx=i,sty=j;
else if(mp[i][j]==4)
enx=i,eny=j;
else if(mp[i][j]!=2)
mp[i][j]^=1;
}cnt=0;
memset(hd,-1,sizeof(hd));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]==1||mp[i][j]==3)
bfs(i,j);
findsmallestlength();
if(dis[(enx-1)*m+eny]==inf)
puts("-1");
else
cout<<dis[(enx-1)*m+eny]<<endl<<num[(enx-1)*m+eny]<<endl;
return 0;
}
by >_< NeighThorn