只用含有 1 的式子构成数字,要求含有 1 的个数最少
121 = 111 + 11 - 1
一开始用的贪心的方法,但是总觉得战战兢兢的,很明显,对于一个数字,要么用比他稍大一号的 111 ,要么用比他稍小一号的 111 ,但是到底用哪个是不确定的。
这个地方就要用到搜索了。显然,缩小过程中 n 的正负对结果无影响。 而且每一步都必须缩小 n. 每一步都差不多缩小一个数量级,妥。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define PII pair<int,int>
#define MS(x,d) memset(x,d,sizeof(x))
#define ALL(x) x.begin(),x.end()
#define ll long long
ll num[20];
ll ans;
void dfs(ll n, ll ta)
{
if(ta>=ans)
return ;
if(n==0)
{
ans=min(ta,ans);
return ;
}
int i=lower_bound(num,num+15,n)-num;
if(num[i]-n<n)
dfs(num[i]-n,ta+i+1);
if(i!=0&&n%num[i-1]<n)
dfs(n%num[i-1],ta+(i)*(n/num[i-1]));
return ;
}
int main()
{
ll n;
cin>>n;
{
num[0]=1;
for(int i=1;i<=15;i++)
num[i]=num[i-1]*10+1;
ans=0x3f3f3f3f;
dfs(n,0);
cout<<ans<<endl;
}
return 0;
}
思路差不多,但是显然更好想的一发代码。直接使用组合来求解。
<pre name="code" class="cpp">#include <cstdio>
#include <iostream>
using namespace std;
long long n;
long long p[16];
long long Count(long long n, int i) {
long long ret = (i+1LL)*(n/p[i]);
n %= p[i];
if (n == 0) return ret;
return ret + min(Count(n, i-1), i+1 + Count(p[i]-n, i-1));
}
int main() {
// freopen("I.txt", "r", stdin);
p[0] = 1;
for (int i = 0; i < 16; i++)
p[i] = p[i-1]*10 + 1;
cin >> n;
cout << Count(n, 15);
return 0;
}