ArabellaCPC 2019 J. Thanos Power 动规

题目大意

  题目目标是得到一个数N,为此可以进行两种操作,一种是加上10x (x>=0),另一种是减去10x (x>=0),求操作次数的最小值。



解法

  首先数N非常大,因此需要用字符串来存储。(这是废话,哈哈哈)先单独来看对每一位的操作,对当前位上的数x,为了使其变为0,我们可以

1.不断执行减操作x次,
2、执行加操作10-x次。

先说一说俺之前的愚蠢做法

刚开始,本憨憨打算用贪心来做,说说我原来神奇的操作,就是从低位向高位处理,如果当前位 i 的数>5,我就对它用操作2,然后对比他高一位i-1位上的数加一;反之就用操作1,结果当然是WA了,后来学习了别人的做法,发现都是用DP做的,回过头来想了好久才发现这个做法错在哪里。
  用对拍和正确代码核对,发现错误的样例种N都含有5,仔细一想发现对 i 位上的5来说,用操作1还是2是不一定的,取决于比它高一位(i-1)上的数,操作1和2对当前位的操作数都是5,但如果用操作2可能会使之后 i-1 位上的数的最小操作次数减少1或者增加1,所以有时用操作1更好,有时操作2更好(详细可以参考N= 75521 ,6535 ,5553 ,自己手动模拟一遍就很好懂了),因此无法用贪心解决。

老老实实用动规8

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <string>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <map>
using namespace std;
#define ms(a, x) memset(a, x, sizeof(a))
#define fore(i, a, n) for (long long i = a; i < n; i++)
#define ford(i, a, n) for (long long i = n - 1; i >= a; i--)
#define si(a) scanf("%d", &a)
#define sl(a) scanf("%lld", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define sll(a, b) scanf("%lld%lld", &a, &b)
#define slll(a, b, c) scanf("%lld%lld%lld", &a, &b, &c)
#define debug(a) cout << a << endl
#define pr(a) printf("%d ",a)
#define prn(a) printf("%d\n",a)
#define endl '\n'
#define pi acos(-1.0)
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define IO ios::sync_with_stdio(false), cin.tie(0)
#define ull unsigned long long
const double eps = 1e-8;
inline int sgn(const double &x) { return x < -eps ? -1 : x > eps; }
typedef long long ll;
const int inf=0x3f3f3f3f;
const int MAXN = 3e5+5;
//表头分割线----------------
int dp[MAXN][2];
//dp数组,第一维表示位数,第二维表示用那种操作,0表示用操作1,1表示用操作2。
//dp数组里面存储的是从最高位到当前位,且在当前位用某种操作后得到的总操作数最小值。
char N[MAXN];
int main()
{ 
	scanf("%s",N+1);
    int len=strlen(N+1);
    dp[1][0]=N[1]-'0';
    dp[1][1]=10-N[1]+'0'+1;
    for(int i=2;i<=len;++i)
    {
        int x=N[i]-'0';
        dp[i][0]=x+min(dp[i-1][0],dp[i-1][1]);
        dp[i][1]=10-x+min(dp[i-1][0]+1,dp[i-1][1]-1);
    }
    int ans=min(dp[len][0],dp[len][1]);
    prn(ans);
}
发布了2 篇原创文章 · 获赞 1 · 访问量 60

猜你喜欢

转载自blog.csdn.net/swiftlife/article/details/105283211
今日推荐