zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:chess(搜索+最短路)

    题目描述

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


    输入格式

    $pig$在下象棋的时候特别喜欢用马,他总是计算着自己的马还需要几步才能吃掉对方的帅,以及方案数的个数,当然$pig$很笨,所以他只能求助于你。
    我们假设在$n imes m$的棋盘上,$pig$的马只能走$1 imes 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,nleqslant 5$。
    对于$100\%$的数据,$m,nleqslant 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++

  • 相关阅读:
    mysql命令行操作 添加字段,修改字段
    编辑器phpstrom的快捷键修改
    echo json数据给ajax后, 需要加上exit,防止往下执行,带上其他数据,到时ajax失败
    多选出差同事id,拼接,去掉最后逗号
    引入的ajax中异步添加联系人
    .NET 4 实践
    使用dynamic和MEF实现轻量级的AOP组件 (3)
    使用dynamic和MEF实现轻量级的AOP组件 (2)
    使用dynamic 和MEF实现轻量级的 AOP 组件 (1)
    AOP-SheepAspect
  • 原文地址:https://www.cnblogs.com/wzc521/p/11354486.html
Copyright © 2011-2022 走看看