题目描述

$pig$在下象棋的时候特别喜欢用马,他总是计算着自己的马还需要几步才能吃掉对方的帅,以及方案数的个数,当然$pig$很笨,所以他只能求助于你。
我们假设在$n\times m$的棋盘上,$pig$的马只能走$1\times 2$的格点,他的马一开始在$st$,对方的帅在$ed$。当然,我们不能忽视友军和敌军,所以如果落点被友军占有,那么就不能飞过去了;如果落点被敌军占有,那么$pig$认为自己这一步赚了,所以不计入总步数。为了简化问题,我们的马在飞的时候不受到敌军限制。


输入格式

$pig$在下象棋的时候特别喜欢用马,他总是计算着自己的马还需要几步才能吃掉对方的帅,以及方案数的个数,当然$pig$很笨,所以他只能求助于你。
我们假设在$n\times m$的棋盘上,$pig$的马只能走$1\times 2$的格点,他的马一开始在$st$,对方的帅在$ed$。当然,我们不能忽视友军和敌军,所以如果落点被友军占有,那么就不能飞过去了;如果落点被敌军占有,那么$pig$认为自己这一步赚了,所以不计入总步数。为了简化问题,我们的马在飞的时候不受到敌军限制。


输出格式

两行。
第一行:一个数,最少情况下实际走的步数。如果没有方案存在,输出$-1$。
第二行:一个数,达到最小值的方案总数,如果两个方案走的空格不同则认为这两个方案不同(详见样例)。这个数保证不超过内设$64$位整数$(long long/int64)$的大小。如果第一行是$-1$,不要输出此行。


样例

样例输入1:

4 5
0 0 0 0 1
0 0 3 0 0
0 0 0 4 0
0 1 0 0 0

样例输出1:

0
1

样例输入2:

4 5
1 0 0 0 0
3 0 0 0 0
0 0 2 0 0
0 0 0 4 0

样例输出2:

2
3


数据范围与提示

样例2解释:

一共有$3$种方案。$X$代表实际走的步数。

1 0 0 0 0 | 1 0 X 0 0 | 1 0 X 0 0
3 0 X 0 0 | 3 0 0 0 0 | 3 0 0 0 X
0 0 2 0 0 | 0 X 2 0 0 | 0 0 2 0 0
0 X 0 4 0 | 0 0 0 4 0 | 0 0 0 4 0

落在敌军的位置敌军就会被吃掉。不要想在两个位置来回跳跃。

数据范围:

对于$30\%$的数据,$m,n\leqslant 5$。
对于$100\%$的数据,$m,n\leqslant 50$。


题解

首先,考场上有好多同学对样例$1$表示很疑惑,那么我再来明确一下题意,题目中所说的空格子为$0$格子,而样例$1$中的两条路径都没有经过$0$格子,所以我们把它们看成一条路径。

其实这样问题无形中变得复杂了,怎么办呢?

最暴力的方法当然是用$hash$表记录一下路径,然后看这条路经有没有出现过,代码繁琐,但也可行。

懒惰的我当然拒绝这样的做法喽,于是我选择建两张图。

第一张就是原图,然后我把权值为$0$的边都缩起来,这样我们就能保证走过的路径不会重复了。

至于统计路径条数,我选择了$SPFA$,他还没有死,不过$BFS$也可行。

这道题的细节极多,需要特别注意的是在建新图的时候不要建重边。

来讲一个故事,标程出锅了,样例也出锅了,阳哥和标程出了一样的锅,于是他$A$了。

再来讲一个故事,三水教授启动重测无敌的$WD$成功避开了这个错误,然后他交的$Python\ 2$。

总之,这道题是一道细节题,慢慢调吧各位。

时间复杂度:$\Theta($玄学$)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec
{
long long nxt;
long long to;
long long w;
}e[100000],ee[100000];
long long head[5000],cnt,headw[5000],cntw;
long long n,m;
long long st,ed;
long long Map[100][100],wzc[100][100];
long long dis[5000];
bool vis1[5000],vis2[5000],spfa[5000],con[5000][5000];
long long que[5000],h[5000][5000];
bool qj[5000][5000];
long long ans[5000];
void add(long long x,long long y,long long w)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
e[cnt].w=w;
head[x]=cnt;
}
void add_w(long long x,long long y)
{
ee[++cntw].nxt=headw[x];
ee[cntw].to=y;
headw[x]=cntw;
}
void SPFA()
{
queue<long long>q;
q.push(st);
spfa[st]=1;
dis[st]=0;
ans[st]=1;
while(!q.empty())
{
long long flag=q.front();
q.pop();
spfa[flag]=0;
for(long long i=headw[flag];i;i=ee[i].nxt)
if(dis[ee[i].to]>dis[flag]+1)
{
dis[ee[i].to]=dis[flag]+1;
ans[ee[i].to]=ans[flag];
if(!spfa[ee[i].to])
{
q.push(ee[i].to);
spfa[ee[i].to]=1;
}
}
else if(dis[ee[i].to]==dis[flag]+1)ans[ee[i].to]+=ans[flag];
}
}
void dfs1(long long x)
{
vis1[x]=1;
for(long long i=head[x];i;i=e[i].nxt)
{
if(!vis1[e[i].to])
{
if(e[i].w)que[++que[0]]=e[i].to;
else dfs1(e[i].to);
}
}
}
void dfs2(long long x)
{
vis2[x]=1;
for(long long i=1;i<=que[0];i++)
if(!con[x][que[i]])
{
h[x][++h[x][0]]=que[i];
con[x][que[i]]=1;
}
for(long long i=head[x];i;i=e[i].nxt)
if(!e[i].w&&!vis2[e[i].to])
dfs2(e[i].to);
}
int main()
{
for(long long i=1;i<=3000;i++)dis[i]=20020923002002092300;
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++)
for(long long j=1;j<=m;j++)
{
scanf("%lld",&Map[i][j]);
wzc[i][j]=++wzc[0][0];
if(Map[i][j]==3)
{
st=wzc[i][j];
Map[i][j]=0;
}
if(Map[i][j]==4)
{
ed=wzc[i][j];
Map[i][j]=0;
}
}
for(long long i=1;i<=n;i++)
for(long long j=1;j<=m;j++)
{
if(Map[i][j]==2)continue;
if(i-1>0&&j-2>0&&Map[i-1][j-2]!=2)
{
if(Map[i-1][j-2])add(wzc[i][j],wzc[i-1][j-2],0);
else add(wzc[i][j],wzc[i-1][j-2],1);
}
if(i-2>0&&j-1>0&&Map[i-2][j-1]!=2)
{
if(Map[i-2][j-1])add(wzc[i][j],wzc[i-2][j-1],0);
else add(wzc[i][j],wzc[i-2][j-1],1);
}
if(i-1>0&&j+2<=m&&Map[i-1][j+2]!=2)
{
if(Map[i-1][j+2])add(wzc[i][j],wzc[i-1][j+2],0);
else add(wzc[i][j],wzc[i-1][j+2],1);
}
if(i-2>0&&j+1<=m&&Map[i-2][j+1]!=2)
{
if(Map[i-2][j+1])add(wzc[i][j],wzc[i-2][j+1],0);
else add(wzc[i][j],wzc[i-2][j+1],1);
}
if(i+1<=n&&j-2>0&&Map[i+1][j-2]!=2)
{
if(Map[i+1][j-2])add(wzc[i][j],wzc[i+1][j-2],0);
else add(wzc[i][j],wzc[i+1][j-2],1);
}
if(i+2<=n&&j-1>0&&Map[i+2][j-1]!=2)
{
if(Map[i+2][j-1])add(wzc[i][j],wzc[i+2][j-1],0);
else add(wzc[i][j],wzc[i+2][j-1],1);
}
if(i+1<=n&&j+2<=m&&Map[i+1][j+2]!=2)
{
if(Map[i+1][j+2])add(wzc[i][j],wzc[i+1][j+2],0);
else add(wzc[i][j],wzc[i+1][j+2],1);
}
if(i+2<=n&&j+1<=m&&Map[i+2][j+1]!=2)
{
if(Map[i+2][j+1])add(wzc[i][j],wzc[i+2][j+1],0);
else add(wzc[i][j],wzc[i+2][j+1],1);
}
}
for(long long i=1;i<=n;i++)
for(long long j=1;j<=m;j++)
if(Map[i][j]==1&&!vis1[wzc[i][j]])
{
que[0]=0;
dfs1(wzc[i][j]);
memset(vis2,0,sizeof(vis2));
dfs2(wzc[i][j]);
}
for(long long i=1;i<=n;i++)
for(long long j=1;j<=m;j++)
{
if(Map[i][j]==2||Map[i][j]==1)continue;
for(long long k=head[wzc[i][j]];k;k=e[k].nxt)
if(e[k].w)
{
if(!qj[wzc[i][j]][e[k].to])
{
qj[wzc[i][j]][e[k].to]=1;
add_w(wzc[i][j],e[k].to);
}
}
else
{
for(long long l=1;l<=h[e[k].to][0];l++)
if(!con[wzc[i][j]][h[e[k].to][l]]&&!qj[wzc[i][j]][h[e[k].to][l]])
{
qj[wzc[i][j]][h[e[k].to][l]]=1;
add_w(wzc[i][j],h[e[k].to][l]);
con[wzc[i][j]][h[e[k].to][l]]=1;
}
}
}
SPFA();
if(dis[ed]==20020923002002092300)puts("-1");
else cout<<dis[ed]-1<<endl<<ans[ed]<<endl;
return 0;
}

rp++

[CSP-S模拟测试]:chess(搜索+最短路)的更多相关文章

  1. [CSP-S模拟测试]:任务分配(最短路+贪心+DP)

    题目传送门(内部题149) 输入格式 每个测试点第一行为四个正整数$n,b,s,m$,含义如题目所述. 接下来$m$行,每行三个非负整数$u,v,l$,表示从点$u$到点$v$有一条权值为$l$的有向 ...

  2. [CSP-S模拟测试]:迷宫(最短路)

    题目传送门(内部题123) 输入格式 输入文件的第一行为四个正整数$n,m,k,d$. 接下来$m$行,每行三个整数$u,v,w$,描述一条无向道路. 输入文件最后一行包含$k$个整数,为$p_0,p ...

  3. [CSP-S模拟测试]:最小距离(最短路)

    题目传送门(内部题97) 输入格式 第一行三个整数$n,m,p$,第二行$p$个整数$x_1\sim x_p$表示特殊点的编号.接下来$m$行每行三个整数$u,v,w$表示一条连接$u$和$v$,长度 ...

  4. [CSP-S模拟测试]:游戏(最短路)

    题目传送门(内部题35) 输入格式 第一行,两个正整数$X,Y$.第二行,三个非负整数$A,B,C$.第三行,一个正整数$N$.接下来$N$行,每行两个非负整数$x_i,y_i$. 输出格式 一行,一 ...

  5. [CSP-S模拟测试]:chess(数学)

    题目描述 $dirty$在一个棋盘上放起了棋子. 棋盘规格为$n\times m$,他希望任意一个$n\times n$的区域内都有$C$个棋子.$dirty$很快就放置好了一个满足条件的棋盘方案,但 ...

  6. NOIP模拟测试19「count·dinner·chess」

    反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...

  7. 模拟测试—moq:简单一两句

    在Xunit的基础上,说话模拟测试. 假如我们有这样一个控制器里面有这样一个方法,如图 我们在对Bar测试得时候,如果测试未通过,错误有可能来至于Bar,也有可能错误来至于serverde Foo方法 ...

  8. [考试反思]1003csp-s模拟测试58:沉淀

    稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...

  9. csp-s模拟测试98

    csp-s模拟测试98 $T1$??不是我吹我轻松手玩20*20.$T2$装鸭好像挺可做?$T3$性质数据挺多提示很明显? $One$ $Hour$ $Later$ 这$T1$什么傻逼题真$jb$难调 ...

随机推荐

  1. DataGridView数值列和日期列

    本文转自:http://www.cnblogs.com/conexpress/p/5923324.html 在使用DataGridView编辑数据的时候,编辑的单元格一般会显示为文本框,逻辑值和图片会 ...

  2. DFS序1

    给一棵有根树,这棵树由编号为1..N的N个结点组成.根结点的编号为R.每个结点都有一个权值,结点i的权值为vi .接下来有M组操作,操作分为两类:1 a x,表示将结点a的权值增加x:2 a,表示求结 ...

  3. 内网渗透 - 权限维持 - Linux

    1.预加载型动态链接库后门2.strace后门3.ssh后门4.OpnenSSH后门5.sshd软链接后门6.wrapper后门7.SUID后门8.inetd服务后门9.协议后门10.vim后门11. ...

  4. [LeetCode]29 两数相除和一个小坑点

    给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 1: 输 ...

  5. 000 (H5*) 知识点总结

    https://note.youdao.com/ynoteshare1/index.html?id=ff02e616917fba868f39241c8383d7c7&type=note 目录 ...

  6. C语言作业总结

    .## 一.我学到的内容 二.我的收获 作业 学到的知识点简介 C语言I博客作业01 学习了markdown语法. C语言I博客作业02 学习了<提问的智慧>. C语言I博客作业03 了解 ...

  7. <每日一题> Day4:CodeForces-1042A.Benches(二分 + 排序)

    题目链接 参考代码: /* 排序 + 每次取小 #include <iostream> #include <algorithm> using namespace std; co ...

  8. Java学习day10-面向对象特征之一:封装和隐藏

    一.包package和引用import 1.关键字package package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包(若缺省该语句,则指定为无名包).包的存在是为了区别同名 ...

  9. FFmpeg从入门到出家(HEVC在RTMP中的扩展)

    由金山云视频云技术团队提供:FFmpeg从入门到出家第三季: 为推进HEVC视频编码格式在直播方案中的落地,经过CDN联盟讨论,并和主流云服务厂商达成一致,规范了HEVC在RTMP/FLV中的扩展,具 ...

  10. java SSM框架 代码生成器 快速开发平台 websocket即时通讯 shiro redis

    A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 , ...