POJ1945 Power Hungry Cows (BFS)

题目大意:自己感觉非常奇葩的一道搜索题。给出n,求x^n。最先给出的两个数为x^1和x^0,可以执行如下操作:两个数相乘,其中一个数平方,两个数相除。问要达到x^n的最少步数。


思路:把此题说得简单一点就是给定两个加数a = 1, b = 0;(在这里我们规定a总是大于b)每一部可以执行a*2,b*2,a-b之一的操作,使得目标状态达到n,每次操作之后新得到的值要替换掉原来的一个数。例如当a = 16,b = 2我们可以得到以下状态:

a = 32,b = 2;   a = 32, b = 16;   a = 16, b = 4;   a = 2,b = 4;   a = 12 ;   a = 18,b = 2;   a = 18, b = 16;    a = 14,b = 2;   a = 16,b = 14;

然后剩下的就是搜索的问题了。

考虑以下情况可以剪枝:显然a = b是可以剪掉的;如果a超过目标状态n太多是没有最优解的,同理,b太大也是没有最优解的。只是我没有完全弄清楚为什么b大于100左右,a超过n 100 左右是没有最优解的。

#include<cstdio>
#include<iostream>
#define MAXN 800000
using namespace std;
struct T
{
	int num1,num2,step;
}q[MAXN];
bool vis[20500][105];
int n;
int head,tail;
bool add(int num1,int num2,int step)//其实就是一个BFS,维护num1 > num2
{
	if(num1 == n||num2 == n)//达到目标状态
	{
		return true;
	}
	if(num1 < num2)
		swap(num1,num2);
		if(num1 == num2||num1 >= n + 101|| num2 >= 101)//两个数相等,则无最优解;第一个数超过n太多无解;第二个数太大会运行错误
		return false;
	if(!vis[num1][num2])//入队列
	{
		vis[num1][num2] = 1;
		tail++;
		q[tail].num1 = num1;
		q[tail].num2 = num2;
		q[tail].step = step;
	}
	return false;
}
int main()
{
	scanf("%d",&n);
	head = tail = -1;
	add(1,0,0);//初始状态的两个数,num1 = 1,num2 = 0
	int num1,num2,step;
	int ans;
	while(head < tail)
	{
		++head;
		num1 = q[head].num1,num2 = q[head].num2,step = q[head].step + 1;
		if(add(num1+num1,num2,step) || add(num1,num2+num2,step) || add(num1,num1+num2,step) || add(num2,num1+num2,step) || add(num1,num1+num1,step) || add(num2,num2+num2,step) || add(num1 - num2,num2,step) || add(num1,num1 - num2,step))//考虑所有保和运算的情况,全部入队
		{
			ans = step;
			break;
		}
	}
	printf("%d\n",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值