Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 162098 | Accepted: 49347 |
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Line 1: Two space-separated integers: N and K
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
5 17
4
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
USACO 2007 Open Silver
对于第i个位置,有三种操作,分别可以走到i - 1, i + 1, i * 2位置,问从位置n走到位置k的最少步骤是多少(其实就是最短路径)
对于这类最短路径我们考虑bfs(广度优先搜索),每一步有三个分支。
如果直接搜索肯定是指数阶级的复杂度,我们需要剪枝来去除无用的节点
1.可行性剪枝:如果当前位置大于k,那么只能不断做X-1操作,而不能使用会使当前位置变大的X+1、2X操作
2.用了可行性剪枝实际还是会超时,因为我们会多次走到相同位置,队列里会产生大量重复节点,而且每次都会push进去的节点数会指数级增长,会导致超时,所以我们还需要用数组标记走过的位置来判重
自认为代码写的还比较优美,注意如果没在bfs里对push进去的节点做范围限制的话,标记数组要开两倍大,不然2X操作会RE
但是我交C++能过,交G++不知道为什么RE了,然后开了三倍大小依然RE,希望有人能告诉我为什么,欢迎拿我代码去实验
#include
#include
#include
using namespace std;
#define mp make_pair
#define fi first
#define se second
typedef pair PII;
const int N = 1e5 + 10;
int vis[N << 1];
queue q;
int main()
{
int n, k;
cin >> n >> k;
q.push(mp(n, 0));
int ans = 0;
while (!q.empty()){
PII tmp = q.front();
q.pop();
if (tmp.fi == k) {
ans = tmp.se;
break;
}else {
if (!vis[tmp.fi - 1])q.push(mp(tmp.fi - 1, tmp.se + 1)), vis[tmp.fi - 1] = 1;
if (tmp.fi < k){
if (!vis[tmp.fi + 1])q.push(mp(tmp.fi + 1, tmp.se + 1)), vis[tmp.fi + 1] = 1;
if (!vis[tmp.fi * 2])q.push(mp(tmp.fi * 2, tmp.se + 1)), vis[tmp.fi * 2] = 1;
}
}
}
cout << ans << endl;
return 0;
}