codevs 2541 幂运算(迭代加深搜索)

/*
一开始想到了简单的深搜 维护当前可用的mi数组
然后回溯用哪个 不断更新新产生的mi
这样的问题是 由于mi不断产生 搜索规模扩大 
不好 不好  下面是奇丑的WA掉的代码 做个反面教材 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,ans=0x3f3f3f3f,f[1055],s[1055],top,vis[1055];
void Dfs(int p,int c)
{
    if(p<=0||p>n*2)return;
    if(f[p]==0)s[++top]=p,f[p]=1;
    if(p==n){ans=min(ans,c);return;}
    if(c>ans)return;
    for(int i=1;i<=top;i++)
      if(vis[i]==0)
        {
          vis[i]=1;
          Dfs(p+s[i],c+1);
          Dfs(p-s[i],c+1);
          vis[i]=0;
        }
}
int main()
{
    scanf("%d",&n);
    ans=n;
    Dfs(1,0);
    printf("%d\n",ans);
    return 0;
}
/*
正解是迭代加深
对于每次的搜索 我们限制最多能做几次运算 
这样搜索的规模就大大减小 
同样的维护已经得到的mi数组
数组的大小对应做了几次运算 
加上几个剪枝:
如果mi中最大的<<(limit-k)都到不了n 搜索失败
生成新的mi的时候 尽量组合数大的 这样也可以减小规模 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 20
using namespace std;
int n,a[N*2];
bool Dfs(int k,int limit)
{
    if(a[k]==n)return 1;
    if(k==limit)return 0;
    int maxx=0;
    for(int i=0;i<=k;i++)maxx=max(maxx,a[k]);
    if(maxx<<(limit-k)<n)return 0;
    for(int i=k;i>=0;i--)
      {
          a[k+1]=a[i]+a[k];
          if(Dfs(k+1,limit))return 1;
          a[k+1]=a[k]-a[i];
          if(Dfs(k+1,limit))return 1;
      }
    return 0;
}
int find()
{
    if(n==1)return 0;
    a[0]=1;
    for(int i=1;i<=N;i++)
      if(Dfs(0,i))return i;
}
int main()
{
    scanf("%d",&n);
    printf("%d\n",find());
    return 0;
}

 

posted @ 2016-06-10 19:56  一入OI深似海  阅读(183)  评论(0编辑  收藏  举报