9.18考试 第三题chess题解

本文解析了一道复杂的棋盘搜索题目,通过缩边技术简化问题,并采用SPFA算法求解最短路径及方案数量。文章详细介绍了实现过程,包括构建边、Tarjan算法寻找强连通分量等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

  在讲这道题之前我们先明确一个丝薄出题人根本没有半点提示却坑死了无数人的注意点:

    走敌人和不走敌人直接到时两种走法,但只走一个敌人和走一大坨敌人到同一个点只算一种方案(当然,前提是步骤一致)。

  当时看完所有题后打算第一个打这道题,当时第一反应以为只是一个普普通通的宽搜,然后就发现我需要记录一下他走过那些敌人,然后就开始懵逼了,dfs能记录但太慢,bfs较快但无法记录,然后我只能在bfs中传递结构体,里面包含一个vector然后就全E了……

  其实当时自己也是犯浑,过于局限于传统的棋盘搜索题了,对于敌人我们可以通过缩边,将敌人两侧的空格连在一起,然后就不必去担心卡死在里面了。不过我的方法相当麻烦,首先先对大棋盘建边,然后挨个tarjan,缩可以相互到达的敌人,然后又得重新建边,然后又需要在新边的基础上去缩边,总共搞了3次,自己都烦了,只能说挺练代码能力的……真的挺练的……

  当然,我们完全可以dfs一下所有的敌人然后对于所有他们能连到的点之间相互建边,结果本博主太懒了,然后打了一个长了不知道几百倍的代码……

  然后就是比较简单的spfa了。

  不过对于第二问的答案,既然人家说了是long long 级别的,就一定有他的道理(虽然刚刚经过本博主踩雷发现改为int完全没问题,丝薄出题人……),所以由于棋盘有一个特殊性质:距离短的一定搜的早,所以我们只用记录一下到该点的方案数,更新距离是直接转移就好了。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<queue>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<map>
  9 #include<vector>
 10 #define N 53
 11 using namespace std;
 12 int n,m,c[N][N],zz1,zz2,zz5,zz,b[N*N],d[N*N],a[N*N];
 13 int zy[10][10];
 14 int bh[N][N];
 15 struct ro{
 16     int to,l;
 17     int next;
 18 }road[N*N*10],road2[N*N*10],road3[N*N*10];
 19 void build2(int x,int y,int z)
 20 {
 21     zz2++;
 22     road2[zz2].to=y;
 23     road2[zz2].next=b[x];
 24     road2[zz2].l=z;
 25     b[x]=zz2;
 26 }
 27 void build3(int x,int y,int z)
 28 {
 29     zz5++;
 30     road3[zz5].to=y;
 31     road3[zz5].l=z;
 32     road3[zz5].next=d[x];
 33     d[x]=zz5;
 34 }
 35 void build(int x,int y)
 36 {
 37     zz++;
 38     road[zz].to=y;
 39     road[zz].next=a[x];
 40     a[x]=zz;
 41     road[zz].l=1;
 42 }
 43 bool check(int x,int y)
 44 {
 45     if(x<=0||x>n)return 0;
 46     if(y<=0||y>m)return 0;
 47     if(c[x][y]==2)return 0;
 48     return 1;
 49 }
 50 bool rz[N*N],rz2[N*N],lt[N*N][N*N],lt2[N*N][N*N],rd[N*N];
 51 int st[N*N*2],top,dfn[N*N],low[N*N],zz3,belong[N*N],zz4,c2[N*N];
 52 void tar(int x)
 53 {
 54     zz3++;
 55     low[x]=dfn[x]=zz3;
 56     rz[x]=rz2[x]=1;
 57     top++;
 58     st[top]=x;
 59     for(int i=b[x];i>0;i=road2[i].next)
 60     {
 61         int y=road2[i].to;
 62         if(road2[i].l==1||c2[x]!=1)continue;
 63         if(!rz2[y])
 64         {
 65             tar(y);
 66             low[x]=min(low[x],low[y]);
 67         }
 68         else if(rz[y])
 69             low[x]=min(low[x],dfn[y]);
 70     }
 71     if(low[x]==dfn[x])
 72     {
 73         int v;
 74         zz4++;
 75         do{
 76             v=st[top];
 77             belong[v]=zz4;
 78             top--;
 79             rz[v]=0;
 80         }while(dfn[v]!=low[v]);
 81     }
 82 }
 83 int dis[N*N],sx,sy,tx,ty,js[N*N];
 84 void spfa()
 85 {
 86     memset(dis,0xf,sizeof(dis));
 87     rd[belong[bh[sx][sy]]]=1;
 88     dis[belong[bh[sx][sy]]]=0;
 89     queue<int> q1;
 90     q1.push(belong[bh[sx][sy]]);
 91     js[belong[bh[sx][sy]]]=1;
 92     while(!q1.empty())
 93     {
 94         int x=q1.front();q1.pop();
 95         rd[x]=0;
 96         if(x==belong[bh[tx][ty]])continue;
 97         for(int i=a[x];i>0;i=road[i].next)
 98         {
 99             int y=road[i].to;
100             if(dis[y]>dis[x]+road[i].l)
101             {
102                 dis[y]=dis[x]+road[i].l;
103                 js[y]=0;
104                 js[y]+=js[x];
105                 if(!rd[y])
106                 {
107                     q1.push(y);
108                     rd[y]=1;
109                 }
110             }
111             else if(dis[y]==dis[x]+road[i].l) js[y]+=js[x];
112         }
113     }
114 }
115 int main()
116 {
117     scanf("%d%d",&n,&m);
118     for(int i=1;i<=n;i++)
119     {
120         for(int j=1;j<=m;j++)
121         {
122             zz1++;
123             bh[i][j]=zz1;
124             scanf("%d",&c[i][j]);
125             c2[zz1]=c[i][j];
126             if(c[i][j]==3)
127                 sx=i,sy=j;
128             else if(c[i][j]==4)
129                 tx=i,ty=j;
130         }
131     }
132     zy[1][0]=-1,zy[1][1]=-2;
133     zy[2][0]=1,zy[2][1]=-2;
134     zy[3][0]=1,zy[3][1]=2;
135     zy[4][0]=-1,zy[4][1]=2;
136     zy[5][0]=-2,zy[5][1]=-1;
137     zy[6][0]=2,zy[6][1]=-1;
138     zy[7][0]=-2,zy[7][1]=1;
139     zy[8][0]=2,zy[8][1]=1;
140     for(int i=1;i<=n;i++)
141     {
142         for(int j=1;j<=m;j++)
143         {
144             for(int k=1;k<=8;k++)
145             {
146                 if(c[i][j]==2)continue;
147                 int tx=i+zy[k][0],ty=j+zy[k][1];
148                 if(!check(tx,ty))continue;
149                 int cj=1;
150                 if(c[tx][ty]==1)cj=0;
151                 build2(bh[i][j],bh[tx][ty],cj);
152             }
153         }
154     }
155     for(int i=1;i<=n;i++)
156     {
157         for(int j=1;j<=m;j++)
158         {
159             if(c[i][j]==2)continue;
160             if(!rz2[bh[i][j]])
161                 tar(bh[i][j]);
162         }
163     }
164     for(int i=1;i<=n;i++)
165     {
166         for(int j=1;j<=m;j++)
167         {
168             
169             if(c[i][j]==2)continue;
170             int t=bh[i][j];
171             for(int k=b[t];k>0;k=road2[k].next)
172             {
173                 int y=belong[road2[k].to];
174                 if(y!=belong[t]&&!lt[belong[t]][y])
175                 {
176                     lt[belong[t]][y]=1;
177                     build3(belong[t],y,road2[k].l);
178                 }
179             }
180         }
181     }
182     memset(lt,0,sizeof(lt));
183     for(int i=1;i<=zz4;i++)
184     {
185         for(int j=d[i];j>0;j=road3[j].next)
186         {
187             int y=road3[j].to;
188             if(road3[j].l==0)
189             {
190                 for(int k=d[y];k>0;k=road3[k].next)
191                 {
192                     int z=road3[k].to;
193                     if(z!=i&&!lt2[i][z])
194                         build(i,z),lt2[i][z]=1;
195                 }
196             }
197             else if(!lt[i][y])
198                   build(i,y),lt[i][y]=1;
199         }
200     }
201     spfa();
202     if(dis[belong[bh[tx][ty]]]==dis[0])
203         printf("-1\n");
204     else
205         printf("%d\n%lld\n",dis[belong[bh[tx][ty]]]-1,js[belong[bh[tx][ty]]]);
206     return 0;
207 }
View Code

 

转载于:https://www.cnblogs.com/liutianrui/p/7552867.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值