白银莲花池
首先,想的是3遍BFS直接求解。
但是发现前两问很好求解,但是如果到第三个问题怎么跑出来都比答案大,
因为一个点可能被增加路径后到它下一个点,之前的路径数会被重复统计。
所以f[ax][ay]+=f[x][y]应该改为f[ax][ay]++,这样就保证每次只会多出一条新的路径。
注意细节实现,同时bfs时开inq[]数组(我的ch[]数组)记录是否在队内。
如果不加,那每个点会被访问多次,导致2个点TLE。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
const int N=35;
ll dp[N][N],dis[N][N],f[N][N];
int n,m;
int sum;
int sx,sy,tx,ty;
int vis[N][N];
int dx[10]={1,-1,2,-2,1,-1,2,-2},dy[10]={2,2,1,1,-2,-2,-1,-1};
bool fg=0,ch[N][N];
queue<pair<int,int> > q,q1,q2;
void bfs(){
while(!q.empty()){
int x=q.front().first;
int y=q.front().second;
ch[x][y]=0;
q.pop();
for(int i=0;i<=7;i++){
int ax=x+dx[i],ay=y+dy[i];
int sum=0;
if(ax>n||ay>m) continue;
if(ax<=0||ay<=0) continue;
if(vis[ax][ay]==2) continue;
if(dp[ax][ay]>dp[x][y]+vis[ax][ay]){
dp[ax][ay]=dp[x][y]+vis[ax][ay];
if(ax==tx&&ay==ty) continue;
if(ch[ax][ay]) continue;
q.push(mp(ax,ay));
ch[ax][ay]=1;
}
}
}
}
void bfs2(){
while(!q1.empty()){
int x=q1.front().first;
int y=q1.front().second;
ch[x][y]=0;
q1.pop();
for(int i=0;i<=7;i++){
int ax=x+dx[i],ay=y+dy[i];
int sum=0;
if(ax>n||ay>m) continue;
if(ax<=0||ay<=0) continue;
if(vis[ax][ay]==2) continue;
if(dp[ax][ay]!=dp[x][y]+vis[ax][ay]) continue;
if(dis[x][y]+1>dis[ax][ay]) {
continue;
}
dis[ax][ay]=dis[x][y]+1;
if(ch[ax][ay]) continue;
q1.push(mp(ax,ay));
ch[ax][ay]=1;
// f[ax][ay]+=f[x][y];
}
}
}
void bfs3(){
while(!q2.empty()){
int x=q2.front().first;
int y=q2.front().second;
ch[x][y]=0;
q2.pop();
for(int i=0;i<=7;i++){
int ax=x+dx[i],ay=y+dy[i];
int sum=0;
if(ax>n||ay>m) continue;
if(ax<=0||ay<=0) continue;
if(vis[ax][ay]==2) continue;
if(dis[x][y]+1!=dis[ax][ay]) {
continue;
}
if(dp[x][y]+vis[ax][ay]!=dp[ax][ay]) continue;
// dis[ax][ay]=stp+1;
f[ax][ay]+=f[x][y];
if(ax==tx&&ay==ty) continue;
if(ch[ax][ay]) continue;
q2.push(mp(ax,ay));
ch[ax][ay]=1;
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int p;
scanf("%d",&p);
if(p==3) {
sx=i,sy=j;
vis[i][j]=0;
}
if(p==4){
tx=i,ty=j;
vis[i][j]=0;
}
if(p==1) vis[i][j]=0;
if(p==0) vis[i][j]=1;
if(p==2) vis[i][j]=2;
}
}
memset(dp,99,sizeof(dp));
memset(dis,99,sizeof(dis));
memset(ch,0,sizeof(ch));
// cout<<dp[1][1];
dp[sx][sy]=0;
q.push(mp(sx,sy));
bfs();
if(dp[tx][ty]==dp[0][0]) {
printf("-1\n");
return 0;
}
else printf("%lld\n",dp[tx][ty]);
dis[sx][sy]=0;
memset(ch,0,sizeof(ch));
q1.push(mp(sx,sy));
bfs2();
printf("%lld\n",dis[tx][ty]);
f[sx][sy]=1;
memset(ch,0,sizeof(ch));
q2.push(mp(sx,sy));
bfs3();
printf("%lld\n",f[tx][ty]);
}
第二种就是在一遍bfs种直接处理答案,
考虑如果荷花数更优,直接把(x,y)的信息给(ax,ay)
如果荷花数相同,但步数更优,同上
如果两个都相同,f[ax][ay]+=f[x][y](方案数)
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
const int N=35;
ll dp[N][N],dis[N][N],f[N][N];
int n,m;
int sum;
int sx,sy,tx,ty;
int vis[N][N];
int dx[10]={1,-1,2,-2,1,-1,2,-2},dy[10]={2,2,1,1,-2,-2,-1,-1};
bool fg=0,ch[N][N];
queue<pair<int,int> > q;
void bfs(int x,int y){
while(!q.empty()){
int x=q.front().first;
int y=q.front().second;
ch[x][y]=0;
q.pop();
for(int i=0;i<=7;i++){
bool fg=0;
int ax=x+dx[i],ay=y+dy[i];
int sum=0;
if(ax>n||ay>m) continue;
if(ax<=0||ay<=0) continue;
if(vis[ax][ay]==2) continue;
if(dp[ax][ay]>dp[x][y]+vis[ax][ay]){
dp[ax][ay]=dp[x][y]+vis[ax][ay];
dis[ax][ay]=dis[x][y]+1;
f[ax][ay]=f[x][y];
if(ax==tx&&ay==ty) continue;
fg=1;
}
else if(dp[ax][ay]==dp[x][y]+vis[ax][ay]&&dis[ax][ay]>dis[x][y]+1){
dp[ax][ay]=dp[x][y]+vis[ax][ay];
dis[ax][ay]=dis[x][y]+1;
f[ax][ay]=f[x][y];
if(ax==tx&&ay==ty) continue;
fg=1;
}
else if(dp[ax][ay]==dp[x][y]+vis[ax][ay]&&dis[ax][ay]==dis[x][y]+1){
f[ax][ay]+=f[x][y];
if(ax==tx&&ay==ty) continue;
fg=1;
}
if(fg&&!ch[ax][ay]){
q.push(mp(ax,ay));
ch[ax][ay]=1;
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int p;
scanf("%d",&p);
if(p==3) {
sx=i,sy=j;
vis[i][j]=0;
}
if(p==4){
tx=i,ty=j;
vis[i][j]=0;
}
if(p==1) vis[i][j]=0;
if(p==0) vis[i][j]=1;
if(p==2) vis[i][j]=2;
}
}
memset(dp,99,sizeof(dp));
memset(dis,99,sizeof(dis));
// cout<<dp[1][1];
dp[sx][sy]=0;
dis[sx][sy]=0;
f[sx][sy]=1;
q.push(mp(sx,sy));
ch[sx][sy]=1;
bfs(sx,sy);
if(dp[tx][ty]==dp[0][0]) {
printf("-1\n");
return 0;
}
else printf("%lld\n",dp[tx][ty]);
printf("%lld\n",dis[tx][ty]);
printf("%lld\n",f[tx][ty]);
}