POJ 1945 Power Hungry Cows
Description
有两个数a、b,初始值分别为x、1,每次可以将a、b中的一个数与自身或另外一个进行乘、除运算,并将结果保存到a或b,求最少用多少次运算能得到x^P。 (P <= 20000)
Analysis
1、广度优先搜索
状态(a,b)代表(x^a, x^b),令a为二者中较大的数,从(a, b)可以转移到8个状态,即(2a, b)、(a+b,b)、(2b,b)、(a,2a)、(a,a+b)、(a,2b)、(a,a-b)、(a-b,a),分别将这8种状态加入队列继续进行搜索,直到a或b等于P。
2、A搜索
设计估价函数f(i) = g(i) + h(i),g(i)是当前步数。h(i)是当前状态到终点步数的预估值。
对于当前状态(a,b),当a小于P式,a成倍地增长(a=2, 即x^a和自己不断地相乘)可以更快的到达P,然后再用减法进行微调, h(i) = log(P/a);当a > P时,由于无法确定减法的次数,为了使h小于实际值,设h(i) = 0。用(a,b,g,h)表示状态,每次取g + h最小的状态进行扩展。
Code
bfs + 剪枝
5312K 485MS
#include <iostream> #include <queue> using namespace std; const int maxn = 20003, maxq = 700003, prime0 = 20101, prime1 = 97; int n, n2, answer; bool hashTable[prime0][prime1]; struct node{ int a, b, step; }; queue<node> q; int gcd (int a, int b) { return b ? gcd (b, a % b) : a; } bool add_node(int a,int b,int step) { if (a == n || b == n) return true; if (a < b) { int temp = a; a = b; b = temp; } if (n % gcd (a, b)) return false; if (a > 2 * n) return false; if (a > n && b == 0) return false; if (a == b || a >= n2 || b >= prime1) return false; if (!hashTable[a][b]) { hashTable[a][b] = true; q. push ({a, b, step}); } return false; } int bfs() { n2 = n + prime1; add_node(1, 0, 0); while(!q.empty()) { int a = q.front().a, b = q.front().b, step = q.front().step + 1; q.pop(); if(add_node(a+a, b, step) || add_node(a+b, b, step) || add_node(b+b, b, step) || add_node(a, a+a, step) || add_node(a, a+b, step) || add_node(a, b+b, step) || add_node(a, a-b, step) || add_node(a-b, a, step)) { answer = step; break; } } return 0; } int main() { cin >> n; bfs(); cout << answer; return 0; }
A* + 剪枝
9776K 47MS
#include <iostream> #include <queue> using namespace std; const int prime0 = 20101, prime1 = 1097; int n, n2, ans; bool hashTable[prime0 + prime1][prime1]; struct node{ int a, b, g, h; bool operator< (const node &a) const { return g + h == a . g + a . h ? h > a . h : g + h > a . g + a . h; } }; node now; priority_queue<node> q; int gcd (int a, int b) { return b ? gcd (b, a % b) : a; } bool add_node(int a,int b) { if (a == n || b == n) return true; if (a < b) { int temp = a; a = b; b = temp; } if (a > 2 * n) return false; if (a > n && b == 0) return false; if (a == b) return false; if (n % gcd (a, b)) return false; if (a >= n2 || b >= prime1) return false; if (!hashTable[a][b]) { hashTable[a][b] = true; int h = 0, tx = a; while (tx < n) h ++, tx <<= 1; q. push ({a, b, now.g + 1, h}); } return false; } int Astar() { n2 = n + prime1; q. push({1, 0, 0, 0}); hashTable[1][0] = true; while(!q.empty()) { now = q.top(); int a = now.a, b = now.b; q.pop(); if(add_node(a+a, b) || add_node(a+b, b) || add_node(b+b, b) || add_node(a, a+a) || add_node(a, a+b) || add_node(a, b+b) || add_node(a, a-b) || add_node(a-b, a)) { ans = now.g + 1; break; } } return 0; } int main() { cin >> n; Astar(); cout << ans; return 0; }
岂能尽如人意,但求无愧我心
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理