一道好题

本文探讨了一种新型的(a,b)-超骑士棋局问题,该问题在一个巨大的矩形棋盘上进行,骑士的跳跃距离被调整。文章通过定义坐标系统来描述骑士的可能移动,并提出一种高效算法来计算特定条件下拥有确切k个有效移动位置的数量。

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

tc srm 559



Problem Statement

 Fernando loves to play chess. One day he decided to play chess on an unusually large rectangular board. To compensate for the board's size he also decided to change the distance a knight can move in a single jump.



To describe the moves easily, we will now introduce a coordinate system. Each cell of the chessboard can be described using two integers (r,c): its row number and its column number. Now, if we have a piece at (r,c), the move (x,y) takes the piece to the cell (r+x,c+y).



The new chess piece will be called an (a,b)-hyperknight. The hyperknight always has 8 possible moves: (+a,+b), (+a,-b), (-a,+b), (-a,-b), (+b,+a), (+b,-a), (-b,+a), and (-b,-a). Note that the original chess knight is a (2,1)-hyperknight.



Of course, as the chessboard is finite, it is not always possible to make each of the 8 moves. Some of them may cause our hyperknight to leave the chessboard. A move is called valid if the destination cell is on the chessboard. Fernando would like to know the number of cells on his board such that his hyperknight will have exactly k valid moves from that cell.



You are given the ints a, b, numRows, numColumns and k. The values numRows and numColumns define the number of rows and number of columns on the chessboard, respectively. The other three values were already explained above. Compute and return the number of cells on the chessboard that have exactly k valid (a,b)-hyperknight moves.

Definition

 
Class:HyperKnight
Method:countCells
Parameters:int, int, int, int, int
Returns:long long
Method signature:long long countCells(int a, int b, int numRows, int numColumns, int k)
(be sure your method is public)
 
 

Notes

-If you wish, you may assume that the rows are numbered 0 through numRows-1 and columns 0 through numColumns-1. However, note that the actual row/column numbers do not matter, as long as they are consecutive.

Constraints

-a will be between 1 and 1,000,000,000 (10^9), inclusive.
-b will be between 1 and 1,000,000,000 (10^9), inclusive.
-a will not be equal to b.
-numRows will be between 1 and 1,000,000,000 (10^9), inclusive.
-numColumns will be between 1 and 1,000,000,000 (10^9), inclusive.
-2*max(a,b) will be strictly less than min(numRows,numColumns).
-k will be between 0 and 8, inclusive.

Examples

0) 
 
2
1
8
8
4
Returns: 20
This is a standard chessboard. We have a traditional chess knight and we are looking for cells such that the knight has exactly 4 valid moves.
1) 
 
3
2
8
8
2
Returns: 16
2) 
 
1
3
7
11
0
Returns: 0
3) 
 
3
2
10
20
8
Returns: 56
4) 
 
1
4
100
10
6
Returns: 564
5) 
 
2
3
1000000000
1000000000
8
Returns: 999999988000000036


这个题目,刚开始拿到一点思路都没有,看了别人的代码,发现原来这么短,想了半个小时才想明白为什么了,确实是一道好题


思路:

 1. 行[ 0 , m-1] ,看起来是总共是m行,其实真正不同的只有4类,[0,a-1] ,[a,b-1] , [ b,m-b-1] , [ m-b,m-a-1] , [m-a , m-1]

 1. 列情况是一样的

然后对于每类区间只要随便枚举其中一个点即可看它能够到达的点是否为k


int _n,_m;
class HyperKnight
{
        public:

        int check(int x,int y)
        {
            if(x>=0&&x<_m&&y>=0&&y<_n) return 1;
            return 0;
        }
        long long countCells(int a, int b, int m, int n, int k)
        {
            if(a>b) swap(a,b);
            _m=m;
            _n=n;
            int xx[]={0,a,b,m-b,m-a,m};
            int yy[]={0,a,b,n-b,n-a,n};
            long long ans=0;
            for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
            {
                int tmp=check(xx[i]+a,yy[j]+b)
                + check(xx[i]+a,yy[j]-b)
                + check(xx[i]-a,yy[j]+b)
                + check(xx[i]-a,yy[j]-b)
                + check(xx[i]+b,yy[j]+a)
                + check(xx[i]+b,yy[j]-a)
                + check(xx[i]-b,yy[j]+a)
                + check(xx[i]-b,yy[j]-a);
                if(tmp==k) ans+=1ll*(xx[i+1]-xx[i])*(yy[j+1]-yy[j]);
            }
            return ans;
        }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值