• 洛谷 P1852 [国家集训队] 跳跳棋


    题目描述

    跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。

    我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)

    跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。

    写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

    输入输出格式

    输入格式:

    第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)

    第二行包含三个整数,表示目标位置x y z。(互不相同)

    输出格式:

    如果无解,输出一行NO。

    如果可以到达,第一行输出YES,第二行输出最少步数。

    输入输出样例

    输入样例#1: 
    1 2 3
    0 3 5
    输出样例#1: 
    YES
    2

    说明

    20% 输入整数的绝对值均不超过10

    40% 输入整数的绝对值均不超过10000

    100% 绝对值不超过10^9

        非常有趣的一道题目。

        可以发现只有唯一的一种方案向里跳,并且一直这样跳最后总会达到一种再也不能向里跳的状态。

        于是我们就可以把向里跳看成在树上向父亲走,而最后b-a = c-b 的状态就是根节点。

        首先如果两个状态的树根不一样,无解;否则就是一个求LCA的问题了,直接倍增即可。

    /*
        向前跳:  a[1] -= a[2]  (须满足 a[1] > a[2])
    	向后跳: a[2] -= a[1] , a[0] += a[1] (须满足 a[1] < a[2])
    	a[1] == a[2] 就不能跳了 
    */
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    struct node{
        int x,y,z;
        bool operator !=(const node &u)const{
        	return x!=u.x||y!=u.y||z!=u.z;
    	}
    }A,B;
    	
    int a[3],b[3];
    unsigned int ans;
    
    node getroot(node x){
    	if(x.y==x.z) return x;
    	
    	if(x.y>x.z) return getroot((node){x.x,(x.y-1)%x.z+1,x.z});
    	
    	else{
    		int o=(x.z-1)/x.y;
    		x.x+=o*x.y,x.z-=o*x.y;
    		return getroot(x);
    	}
    }
    
    int getdeep(node x){
    	if(x.y==x.z) return 0;
    	
    	if(x.y>x.z){
    		int o=(x.y-1)/x.z;
    		x.y-=o*x.z;
    		return getdeep(x)+o;
    	}
    	
    	else{
    		int o=(x.z-1)/x.y;
    		x.x+=o*x.y,x.z-=o*x.y;
    		return getdeep(x)+o;
    	}	
    }
    
    node getnode(node x,int lef){
    	if(x.y==x.z) return x;
    	
    	if(x.y>x.z){
    		int o=(x.y-1)/x.z;
    		
    		if(o>=lef) return (node){x.x,x.y-lef*x.z,x.z};
    		
    		x.y-=o*x.z;
    		return getnode(x,lef-o);
    	}
    	
    	else{
    		int o=(x.z-1)/x.y;
    		
    		if(o>=lef) return (node){x.x+lef*x.y,x.y,x.z-lef*x.y};
    		
    		x.x+=o*x.y,x.z-=o*x.y;
    		return getnode(x,lef-o);
    	}		
    }
    
    inline void solve(){
    	int da=getdeep(A),db=getdeep(B);
    	if(da<db) swap(da,db),swap(A,B);
    	if(da>db) A=getnode(A,da-db);
    	
    	ans=da-db;
    	
    	if(!(A!=B)) return;
    	
    	for(int i=log(db)/log(2)+1;i>=0;i--) if((1<<i)<=db){
    		node AA=getnode(A,1<<i);
    		node BB=getnode(B,1<<i);
    		if(AA!=BB) A=AA,B=BB,ans+=1<<(i+1);
    	}
    	
    	ans+=2;
    }
    
    int main(){
    	for(int i=0;i<3;i++) scanf("%d",a+i);
    	for(int i=0;i<3;i++) scanf("%d",b+i);
    	sort(a,a+3),sort(b,b+3);
    	
    	for(int i=2;i;i--) a[i]-=a[i-1],b[i]-=b[i-1];
    	
    	A=(node){a[0],a[1],a[2]},B=(node){b[0],b[1],b[2]};
    	if(getroot(A)!=getroot(B)){ puts("NO"); return 0;}
    	
    	solve();
    	
    	puts("YES"); 
    	printf("%u
    ",ans);
    	
    	return 0;
    }
    

      

  • 相关阅读:
    MVC各部分技术体现
    SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
    my SQL Workbench创建数据库
    哪些素质很重要,却是读书学不来
    给程序员最好的18个忠告!
    互联网协议入门(二)
    互联网协议入门(一)
    div+css命名规范大全
    javascript中this的用法
    XHTML 相对路径与绝对路径
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9172432.html
Copyright © 2020-2023  润新知