博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
跳跳棋
阅读量:4951 次
发布时间:2019-06-12

本文共 3502 字,大约阅读时间需要 11 分钟。

其实这道题并不是很难,但是确实不太好想啊。。。

题目大意:

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

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

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

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

我们仔细的剖析一下题意:

我们从题目中可知,一共只有三种移动方式:

1.中间的棋子往左跳

2.中间的棋子往右跳

3.两边离中间近的棋子往中间跳(因为如果是远的棋子的话就会跳过两个了。。。)

那么我们知道,如果不断进行第三步操作,最后一定会得到中间棋子到两边距离相等的情况,那么如果两种摆放方式经过这种迭代后,到中间距离相等,那么就代表他们是可以互相转换的,反之则不能。

那么我们就可以判断是否可以完成任务了,而且我们知道棋子看的是相对位置,那么a   b        c,将a跳到bc中间就等于a,b同时向右移ab的差值,但是我们发现每一次减速度太慢,所以我们大可以将每一次移动差值步改为移动另一个差值%这个差值步,想一想正确性?

那么,我们怎么计算需要多少步呢?由于我们知道每一次都有三种选择,那么如果我们从距离相等的情况开始拓展,那么就会有两种选择。也就是这些状态构成了一颗二叉树。

那么我们所求的答案就是树上两点间距离啦!

这个建一个树当然也可以,或者直接判断也行。。。

关于时间复杂度,由于取模运算和gcd比较类似,所以忽略常数影响,应该是log级别的:logx(x是给出的最大距离差)

最后,附上本题代码:

1 #include
2 #include
3 4 //Debug Yufenglin 5 #define debugj printf("Running\n"); 6 #define debugp1(x) printf("%d\n",x); 7 #define debugp2(x,y) printf("%d %d\n",x,y); 8 #define debugp3(x,y,z) printf("%d %d %d\n",x,y,z); 9 10 //Standfor Yufenglin 11 #define LL long long 12 #define LB long double 13 #define reg register 14 #define il inline 15 #define inf 1e8 16 #define maxn 1e5 17 18 using namespace std; 19 20 struct state 21 { 22 int x,y,z; 23 }; 24 state pre,now,c1,c2,ct1,ct2; 25 26 int abs(int x) 27 { 28 if(x<0) return -x; 29 return x; 30 } 31 void merge(state &w) 32 { 33 if(w.x>w.y) swap(w.x,w.y); 34 if(w.y>w.z) swap(w.y,w.z); 35 if(w.x>w.y) swap(w.x,w.y); 36 } 37 bool judge(state a,state b) 38 { 39 if(a.x==b.x&&a.y==b.y&&a.z==b.z) return 1; 40 return 0; 41 } 42 int find_father(state &w) 43 { 44 int step=0; 45 while(w.x+w.z!=2*w.y) 46 { 47 int s1=w.y-w.x,s2=w.z-w.y; 48 if(s1>s2) 49 { 50 int tep=s1/s2; 51 if(s1%s2==0) tep--; 52 w.y-=tep*s2; 53 w.z-=tep*s2; 54 merge(w); 55 step+=tep; 56 } 57 else 58 { 59 int tep=s2/s1; 60 if(s2%s1==0) tep--; 61 w.x+=tep*s1; 62 w.y+=tep*s1; 63 merge(w); 64 step+=tep; 65 } 66 } 67 return step; 68 } 69 state update(state w,int mid) 70 { 71 merge(w); 72 while(mid!=0) 73 { 74 int s1=w.y-w.x,s2=w.z-w.y; 75 if(s1>s2) 76 { 77 int tep=s1/s2; 78 if(s1%s2==0) tep--; 79 tep=min(tep,mid); 80 w.y-=tep*s2; 81 w.z-=tep*s2; 82 merge(w); 83 mid-=tep; 84 } 85 else 86 { 87 int tep=s2/s1; 88 if(s2%s1==0) tep--; 89 tep=min(tep,mid); 90 w.x+=tep*s1; 91 w.y+=tep*s1; 92 merge(w); 93 mid-=tep; 94 } 95 } 96 return w; 97 } 98 int main() 99 {100 scanf("%d%d%d%d%d%d",&pre.x,&pre.y,&pre.z,&now.x,&now.y,&now.z);101 merge(pre),merge(now);102 c1=pre,c2=now;103 int temp1=find_father(pre),temp2=find_father(now);104 if(judge(pre,now)==0) printf("NO\n");105 else106 {107 int dt=abs(temp1-temp2),l=0,r=min(temp1,temp2),ans;108 if(temp1
>1;113 ct1=update(c1,mid);114 ct2=update(c2,mid);115 if(judge(ct1,ct2)==1) ans=mid,r=mid-1;116 else l=mid+1;117 }118 printf("YES\n%d\n",dt+ans*2);119 }120 return 0;121 }

 

转载于:https://www.cnblogs.com/yufenglin/p/10629165.html

你可能感兴趣的文章
两个表格中数据不用是一一对应关系--来筛选不同数据,或者相同数据
查看>>
前端之路
查看>>
javascript 继承
查看>>
String类型转int类型方法
查看>>
关于渲染引擎设计,Scene Management的文章
查看>>
oracle 使用leading, use_nl, rownum调优
查看>>
客户数据库出现大量cache buffer chains latch
查看>>
機械の総合病院 [MISSION LEVEL: C]
查看>>
实战练习细节(分行/拼接字符串/字符串转int/weak和copy)
查看>>
Strict Standards: Only variables should be passed by reference
查看>>
hiho_offer收割18_题解报告_差第四题
查看>>
AngularJs表单验证
查看>>
静态方法是否属于线程安全
查看>>
fegin 调用源码分析
查看>>
Linux的基本命令
查看>>
02号团队-团队任务3:每日立会(2018-12-05)
查看>>
sql 语法大全
查看>>
SQLite移植手记1
查看>>
Java AmericanFlagSort
查看>>
Mysql远程连接报错
查看>>