1 条题解

  • 0
    @ 2025-5-22 13:20:57

    国际象棋一步将死问题题解

    题目分析

    题目要求判断是否存在一步移动白后即可将死黑王的走法。将死的条件是:
    11. 黑王当前处于被攻击状态(将军)。
    22. 黑王无法通过任何合法移动(88个相邻格子)逃脱攻击(所有可能的移动位置均被白方控制或越界)。

    算法思路

    11. 输入处理:将输入的位置(如a3a3)转换为棋盘坐标(xx,yy),其中xx11-88(对应aa-hh),yy11-88(对应11-88)。
    22. 枚举白后的所有合法移动:白后可沿88个方向(上下左右、44个对角线)移动任意格,但路径不能穿过白王或黑王的位置。
    33. 检查将死条件:对每个白后的目标位置,判断是否满足:

    • 黑王被白后攻击(同一行/列/对角线)。
    • 黑王的所有可能移动位置(88个相邻格子)均被白王或白后攻击,或越界。
      44. 选择最优解:若存在多个将死位置,选择列最小(xx最小)、行最小(yy最小)的位置。

    代码关键细节解释

    11. 方向数组

    int dx[9]={0,0,1,-1,1,1,-1,-1,0};
    int dy[9]={1,-1,0,0,1,-1,1,-1,0};
    

    dxdxdydy表示王的99种可能移动方向(包括88个相邻方向和原地)。但实际王不能留在原地,因此代码中会过滤越界的情况。

    22. checkcheck函数(判断是否将死)

    函数逻辑:遍历黑王的所有可能移动位置(88个相邻格子),检查每个位置是否被白方控制。

    • 对于每个黑王可能的移动位置(bxbx,byby):
      • 检查是否被白王攻击:白王的88个相邻格子是否覆盖(bxbx,byby)。
      • 检查是否被白后攻击:白后的88个方向路径上是否覆盖(bxbx,byby)(路径不能穿过白王)。
    • 若所有黑王的移动位置均被控制,则当前白后位置是将死位置。

    33. 枚举白后的移动路径

    白后沿88个方向移动,每个方向枚举所有可能的终点(直到越界或被白王/黑王阻挡):

    for(int i=0;i<8;i++) {  // 8个方向
        for(int j=1;;j++) {  // 沿当前方向移动j步
            int x=wqx+dx[i]*j;
            int y=wqy+dy[i]*j;
            if(x<1||x>8||y<1||y>8) break;  // 越界
            if(x==wkx && y==wky) break;    // 被白王阻挡
            if(x==bkx && y==bky) break;    // 被黑王阻挡
            // 检查当前(x,y)是否能将死
            if(check(x,y)) {
                // 记录最优解(x最小,y最小)
            }
        }
    }
    

    44. 最优解选择

    遍历所有可能的将死位置,选择列最小(xx最小)、行最小(yy最小)的位置。

    示例分析(输入a3a3 g2g2 a1a1

    • 白王位置a3a3x=1x=1,y=3y=3),白后位置g2g2x=7x=7,y=2y=2),黑王位置a1a1x=1x=1,y=1y=1)。
    • 白后移动到a2a2x=1x=1,y=2y=2):
      • 白后与黑王在同一列(x=1x=1),形成将军。
      • 黑王的可能移动位置为:
        • (11,22):被白后占据(攻击)。
        • (22,11):被白王(x=1x=1,y=3y=3的相邻格子包括 (22,22),(22,33)等,但 (22,11)是否被白王攻击?需计算白王的88个相邻格子是否覆盖 (22,11)。
        • 其他位置可能越界或被白后攻击。
      • 所有移动位置均被控制,因此a2a2是将死位置。

    总结

    本题核心是枚举白后的所有合法移动,并验证每个位置是否满足将死条件。关键在于正确实现将死的判断逻辑(黑王的所有移动均被控制),以及白后移动路径的合法性检查(不穿过其他棋子)。通过方向数组和循环枚举,确保覆盖所有可能的情况。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <string>
    int wqx,wqy,wkx,wky,bkx,bky;
    using namespace std;
    //英语     看博友分析     抄博友程序     
    int dx[9]={0,0,1,-1,1,1,-1,-1,0};
    int dy[9]={1,-1,0,0,1,-1,1,-1,0};
    bool check(int x,int y)
    {
    	//cout<<"check "<<x<<" "<<y<<endl;
    	bool flag=true;
    	for(int i=0;i<9;i++)
    	{
    		int bx=bkx+dx[i];
    		int by=bky+dy[i];
    		//cout<<bx<<" "<<by<<endl;
    		if(bx<1 || bx>8 || by<1 ||by>8)
    		{
    			continue;
    		}
    		bool f=false;
    		for(int j=0;j<8;j++)//白王 
    		{
    			int tkx=wkx+dx[j];
    			int tky=wky+dy[j];
    			if(tkx<1 || tkx>8 || tky<1 || tky>8)
    			{
    				continue;
    			}
    			if(tkx==bx && tky==by)
    			{
    				f=true;
    			}
    		}
    		for(int j=0;j<8;j++)//白后
    		{
    			for(int k=1;;k++)
    			{
    				int tqx=x+dx[j]*k;
    				int tqy=y+dy[j]*k;
    				if(tqx<1 || tqx>8 || tqy<1 || tqy>8)
    				{
    					break;
    				}
    				if(tqx==wkx && tqy==wky)
    				{
    					break;
    				}		
    				if(tqx==bx && tqy==by)
    				{
    					f=true;
    				}		
    			} 
    		}
    		//cout<<"f "<<f<<endl;
    		if(f==false)
    		{
    			flag=false;
    		} 
    	}
    	//cout<<"flag "<<flag<<endl;
    	return flag;
    }
    int main()
    {
    	string wq,wk,bk;
    	cin>>wk>>wq>>bk;
    	wqx=wq[0]-'a'+1;
    	wqy=wq[1]-'0';
    	wkx=wk[0]-'a'+1;
    	wky=wk[1]-'0';
    	bkx=bk[0]-'a'+1;
    	bky=bk[1]-'0';
    	int flag=false;
    	int jx=10;
    	int jy=10;
    	for(int i=0;i<8;i++)
    	{
    		for(int j=1;;j++)
    		{
    			int x=wqx+dx[i]*j;
    			int y=wqy+dy[i]*j;
    			if(x<1||x>8||y<1||y>8)
    			{
    				break;
    			}
    			if(x==wkx && y==wky)
    			{
    				break;
    			}
    			if(x==bkx && y==bky)
    			{
    				break;
    			}
    			if(check(x,y))
    			{
    				flag=true;
    				if(jx>x)
    				{
    					jx=x;
    					jy=y;					
    				}else if(jx==x && jy>y)
    				{
    					jx=x;
    					jy=y;					
    				}
    			}
    		}
    	}
    	if(flag==false)
    	{
    		cout<<"no"<<endl;
    	}else
    	{
    		cout<<(char)(jx-1+'a')<<jy<<endl;
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    648
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    2
    已通过
    1
    上传者