题意:
给出一个大数,有两种操作:加 1 0 x 10^x 10x和减 1 0 x 10^x 10x,x随意,不限使用次数,使得大数变为0,求最少的操作次数。
思路:
首先对一个位置上的数a,可以操作a次把这位减为0,或者操作10-a次向上进位,再加上一位就要多花费一次。
定义:
dp[pos][0]:到位置pos且位置为pos的数选择减为0的总花费
dp[pos][1]:到位置pos且位置为pos的数选择向上补成10的花费
对于一个位置,来自低位的进位最多会给它带来1的花费。
那么从高位向低位枚举就没有后效性了。
转移方程:
dp[pos][0]=num[pos]+min(dp[pos-1][0],dp[pos-1][1])
dp[pos][1]=10-num[pos]+min(dp[pos-1][0]+1,dp[pos-1][1]-1)
参考代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
char s[N];
int len;
int dp[N][2];
int main(){
scanf("%s",s+1);
len=strlen(s+1);
dp[1][0]=s[1]-'0';
dp[1][1]=10-s[1]+'0'+1;
for(int i=2;i<=len;i++){
dp[i][0]=s[i]-'0'+min(dp[i-1][0],dp[i-1][1]);
dp[i][1]=10-s[i]+'0'+min(dp[i-1][0]+1,dp[i-1][1]-1);
//printf("%d %d\n",dp[i][0],dp[i][1]);
}
printf("%d\n",min(dp[len][0],dp[len][1]));
return 0;
}