/* 一开始想到了简单的深搜 维护当前可用的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; }
时间: 2024-12-28 21:06:05