牛客国庆集训派对Day3 A Knight

题目:点击打开链接

题意:略。

分析:规律题,打了表半天没找出规律。。。

网友思路:

如果目的点不在第一象限,将其转化到第一象限,且另m>n
若2*n>m>n
    若(n+m)是三的倍数,我可以通过走x个(1,2)和y个(2,1)到达,那么x+2x+2y+y=n+m,得x+y=(n+m)/3;
    若(n+m)%3==1,我可以走这样一步使得(-2,1),使得目的地和起点的曼哈顿距离还是3的倍数,因此答案是(n+m)/3+1
    若(n+m)%3==2,我可以走两步(-2,1),使得目的地和起点的曼哈顿距离还是3的倍数,因此答案是(n+m)/3+2
若m==2*n
   答案是n
若m>2*n
    第一种情况:
    我先尽量走(1,2),直到把n走完,走了n步,若把这时的点看做原点,目的地就是(m-2*n,0),
    转化成起点和目的点在同一直线上的问题
    第二种情况:
    我先走一步(-1,2),然后把(-1,2)当做起点,目的点变成(n+1,m-2)这时在求1+query(n+1,m-2)即可
    答案是两种情况中小的那个
    至于怎么求目的点和起点在同一坐标轴的问题,随便推理一下就知道了

题解:

不妨假设 x>=y>=0。
当 x<=2y 时,定义每一步的冗余值 wi=3-dx-dy,那么∑wi=∑(2-dx)=3*
步数-x-y,显然我们只需要最小化冗余值。我们先只用(+2,+1)(若 x 为奇数则
加一步(+1,+2))走到(x,y’),然后通过将(+2,+1)替换为 2 个(+1,+2)使得
0<=y-y’<3。
若 y-y’=0,则冗余值为 0,显然最小。
若 y-y’=1,则将(+1,+2)替换为(+2,+1)和(-1,+2)或将 2 个(+2,+1)替换为
(+1,+2),(+1,+2),(+2,-1),冗余值为 2,显然最小。(此处需要特判(2,2))
若 y-y’=2,则加上(+2,+1)和(-2,+1),冗余值为 4,由于不存在冗余值为 1
的步,所以最小

 x>2y 时,定义每一步的冗余值 wi=2-dx,那么∑wi=∑(2-dx)=2*步数-x,
显然我们只需要最小化冗余值。我们先只使用(+2,+1)走到(2y,y),然后用
(+2,+1)和(+2,-1)走到(x’,y)使得 0<=x-x’<4。
若 x-x’=0 则冗余值为 0,显然最小

若 x-x’=1 则将之前的(+2,+1)改为(+1,+2)和(+2,-1),冗余值为 1,显然最
小。(此处需要特判(1,0))
若 x-x’=2 则加上(+1,+2)和(+1,-2),冗余值为 2,由 x/2+y 的奇偶性可知
最小。
若 x-x’=3 则加上(+2,+1),(+2,+1),(-1,-2),冗余值为 3,由 x/2+y 的奇偶
性可知最小。
时间复杂度 O(t)

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define pt(a) cout<=a;i--)
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
typedef pair PII;
const ll mod = 1e9+7;
const int N = 1e6+10;ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int to[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};ll t,n,m,ans;ll gn(int x,int y) { ///max(n,m)<=2的情况特判if(x+y==0) return 0;else if(x+y==1) return 3;else if(x+y==2) return 2;else if(x+y==3) return 1;else return 4;
}ll ln(ll x) {///在同一条线上的情况if(x==0) return 0;else if(x==1) return 3;else if(x%4==0) return x/2;else if(x%2==0) return x/2+1;else if((x/2)%2) return x/2+2;else return x/2+1;
}ll sv(ll x,ll y) {ll s1,s2;s1=y+ln(x-2*y);x-=2,y+=1;///绕一步(规律)if(x<=2) s2=1+gn(x,y);else if(x>2*y) s2=1+y+ln(x-2*y);else if(x==2*y) s2=1+y;else if(x<2*y) s2=1+(x+y)/3+(x+y)%3;return min(s1,s2);///取最小
}int main() {ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>t;while(t--) {cin>>n>>m;n=abs(n),m=abs(m);if(n2*m) ans=sv(n,m);else ans=(n+m)/3+(n+m)%3;cout<

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部