UVA 1374 Power Calculus

来源:互联网 发布:windows系统备份还原 编辑:程序博客网 时间:2024/06/05 15:27

题意:给一个数n,求最少需要多少步操作能从1变成n,可以相加相减,不能出现负数

解题思路:迭代加深搜索IDA*.当前状态是已经得到的指数集合,操作是任选两个数进行加法和减法,为了尽快接近目标,不应该任选两个数,应该先选择较大的数,并且先试加法后试减法(这种技巧成为结点排序)。如果当前序列最大的数乘以2^(maxd-d)之后仍小于n,则剪枝。举个例子:假设还剩4步,当前序列中最大的数为6。6+6=12,12+12=24,24+24=48,48+48=96,每次都加上当前序列中最大的数,也就是6*2^4=96,假设n=100,而96<100就要剪枝。

<<左移运算符,左移n位等于乘以2^n;>>右移运算符,右移n位等于除以2^n

代码:

#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <cmath>#include <cstdio>using namespace std;int a[50],n,maxd;bool dfs(int v,int d,int maxd)//v是当前深度对应的n,d是当前深度,maxd是深度上限{    if(d>maxd)return false;    if((a[d]=v)<<(maxd-d)<n)return false;//a[d]=v深度为d时的n等于v    if(v==n||v<<(maxd-d)==n)return true;    for(int i=0;i<=d;i++)//遍历    {        if(dfs(v+a[i],d+1,maxd))return true;        if(v-a[i]>0&&dfs(v-a[i],d+1,maxd))return true;    }    return false;}int main(){    while(cin>>n&&n)    {        for(maxd=0;;maxd++)        {            if(dfs(1,0,maxd))break;        }        cout<<maxd<<endl;    }    return 0;}



原创粉丝点击