标签:mat 调用 这一 std can 剪枝 test mes 无法
这一题可以反向思考,考虑如何从x得到0.因为本题的倍乘机制决定了即使我们用更小的代价到达了更大的x值,这个x值不一定会在最优路线中被用到.因此正向递推的思路因为无法确定最优路线,将导致剪枝困难.而如果如果反向递推,当前值为偶数时的最优情况比较特殊,递归调用树的分支将大大减少,可以将搜索的时空消耗减少至可接受范围.
记f(x)为经过若干次操作,使x的值变为0的最小花费.则f(x)的递推公式为:
证明:
当x为奇数时,显然
当x为偶数时
而
显然由\(f(x)\)推至\(f(x-1)\)时,\(f(x-1)\) 不等于 \(f(x)+c\)
所以
同理可得
代入得:
\(f \left( \frac{x}{2} \right) +b \,\) 一定比 \(f \left( \frac{x}{2}-1 \right) +b+2*a\) 更优
因此
继续向下递推至0后可以得到:
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll> m;
ll x,a,b,c,cnt=0;
ll dfs(ll x)
{
cnt++;
if(m[x])return m[x]-1;
if(x==0)return 0;
if(x==1)return a;
if(x%2==0)m[x]=min(dfs(x/2)+b,x*a)+1;
else m[x]=min(dfs(x-1)+a,dfs(x+1)+c)+1;
return m[x]-1;
}
int main()
{
while(~scanf("%lld %lld %lld %lld",&x,&a,&b,&c))
{
m.clear();
printf("%lld\n",dfs(x));
}
return 0;
}
标签:mat 调用 这一 std can 剪枝 test mes 无法
原文地址:https://www.cnblogs.com/ambrumf/p/14775284.html