首页 > 代码库 > BZOJ2144 跳跳棋

BZOJ2144 跳跳棋

蒟蒻只会广搜。。。20分。。。

后来发现对于一个状态,中间的一个棋子可以往两边跳,而两边的棋子最多只有一个可以往中间跳(怎么发现的?废话嘛、、、!)

故每个状态看做一个点,有关连的状态连起来,就形成了一棵二叉树

对于一个某个有解的状态而言,中间往两边跳的两个状态是它的儿子,两边往中间跳的状态是它的父亲

于是就变成了树上两点求距离问题。

暴力还是不行,只有40分。。。

hzwer:"我们发现若记前两个数差t1,后两个数差t2,不妨设t1<t2

则左边最多往中间跳(t2-1)/t1次

然后只能右边往中间跳,是一个辗转相除的过程,即在logK的时间内我们可以用这种方法得到某个结点它向上K次后的结点,或者根节点,同时还可以顺便算下深度"

好像挺对?Orz。。。

于是就变成了先把两个节点调到树上同一深度再二分LCA的深度即可,做完了。。。

 

 1 /************************************************************** 2     Problem: 2144 3     User: rausen 4     Language: C++ 5     Result: Accepted 6     Time:0 ms 7     Memory:804 kb 8 ****************************************************************/ 9  10 #include <cstdio>11 #include <algorithm>12  13 using namespace std;14 const int INF = (int) 1e9;15 struct data{16     int a[4];17 };18 inline bool operator != (const data a, const data b){19     return a.a[1] != b.a[1] || a.a[2] != b.a[2] || a.a[3] != b.a[3];20 }21 int t1, t2, tmp, ans;22 int a[4], b[4];23  24 data calc(int *a, int k){25     data res;26     int t1 = a[2] - a[1], t2 = a[3] - a[2], i, t;27     for (i = 1; i < 4; ++i)28         res.a[i] = a[i];29     if (t1 == t2) return res;30     if (t1 < t2){31         t = min(k, (t2 - 1) / t1);32         k -= t, tmp += t;33         res.a[2] += t * t1, res.a[1] += t * t1;34     }else{35         t = min(k, (t1 - 1) / t2);36         k -= t, tmp += t;37         res.a[2] -= t * t2, res.a[3] -= t * t2;38     }39     return k ? calc(res.a, k) : res;40 }41  42 int main(){43     int d1, d2, i;44     data t1, t2;45     for (i = 1; i < 4; ++i)46         scanf("%d", a + i);47     for (i = 1; i < 4; ++i)48         scanf("%d", b + i);49     sort(a + 1, a + 4);50     sort(b + 1, b + 4);51     t1 = calc(a, INF), d1 = tmp, tmp = 0;52     t2 = calc(b, INF), d2 = tmp, tmp = 0;53     if (t1 != t2){54         puts("NO");55         return 0;56     }57     if (d1 > d2){58         swap(d1, d2);59         for (i = 1; i < 4; ++i)60             swap(a[i], b[i]);61     }62     ans = d2 - d1;63     t1 = calc(b, ans);64     for (i = 1; i < 4; ++i)65         b[i] = t1.a[i];66     int l = 0, r = d1, mid;67     while (l <= r){68         mid = l + r >> 1;69         if (calc(a, mid) != calc(b, mid)) l = mid + 1;70         else r = mid - 1;71     }72     puts("YES");73     printf("%d\n", ans + 2 * l);74     return 0;75 }
View Code

 

BZOJ2144 跳跳棋