leetcode-1449-数位成本和为目标值的最大数字

数位成本和为目标值的最大数字

题面

leetcode题目

给你一个整数数组 \(cost\) 和一个整数 \(target\) 。请你返回满足如下规则可以得到的 最大 整数:

  • 给当前结果添加一个数位\((i + 1)\)的成本为 \(cost[i]\) (\(cost\) 数组下标从 \(0\) 开始)。
  • 总成本必须恰好等于 \(target\) 。
  • 添加的数位中没有数字 \(0\)

由于答案可能会很大,请你以字符串形式返回。

如果按照上述要求无法得到任何整数,请你返回 "0" 。

example

输入:\(cost = [4,3,2,5,6,7,2,5,5]\), \(target = 9\)
输出:"7772"
解释:添加数位 '7' 的成本为 \(2\) ,添加数位 '2' 的成本为 \(3\) 。所以 "7772" 的代价为 \(2\times 3+ 3\times 1 = 9\) 。 "977" 也是满足要求的数字,但 "7772" 是较大的数字。
数字 成本
1 -> 4
2 -> 3
3 -> 2
4 -> 5
5 -> 6
6 -> 7
7 -> 2
8 -> 5
9 -> 5

数据范围

  • \(cost.length == 9\)
  • \(1 \leq cost[i] \leq 5000\)
  • \(1 \leq target \leq 5000\)

题解

总体思路

考虑\(dp[i][j]\)表示当\(target = i\)时的最大数字对应的数字\(j\)\(dp[i][j]\)个,那么有: \[ tmp_k[i][j] = \left\{ \begin{array}{rcl} dp[i-cost[k]][j] & & { cost [k] \leq i \land }\\ dp[i-cost[k]][j] + 1 & & {cost [k] \leq i \land k + 1 = j } \end{array} \tag{1}\right. \] 则: \[ dp[i][j] = max(tmp_k[i][j]) \qquad k \in \{0,1,2,3,4,5,6,7,8\} \tag{2}\] 那么现在我们只需要考虑\(max\)如何取得才能满足构成最大数字就能实现闭环。我们这样考虑:对于\(tmp_a[i]\)\(tmp_b[i]\),只要有:

  • \(sum_{k=1}^{9} tmp_a[i] > sum_{k=1}^{9} tmp_b[i]\)
  • \(tmp_a[i][j] > tmp_b[i][j]\)\(j\)为从\(9\)\(1\)第一个满足\(tmp_a[i][j]\neq tmp_b[i][j]\)的数 两个条件之一,则可表示$tmp_a[i] > \(tmp_b[i]\)
    这是因为:
  • 如果满足条件1,那么我们总是可以将\(tmp_a[i]\)表示成一个位数比\(tmp_b[i]\)多的数,自然是比较大的。
  • 如果满足条件2,我们从9开始往1构造,大的数在前,由于存在一个数在\(tmp_a[i]\)\(tmp_b[i]\)中位数不同且前者多,那么此时可以明显的得到某一个高位前者是要大一些的。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <map>
#include <string>
using namespace std;
#define _DEBUG

class Solution
{
public:
string largestNumber(vector<int> &cost, int target)
{
int dp[target + 1][10];
memset(dp, 0, sizeof(dp));
dp[0][0] = -1;
for (int i = 1; i \leq target; i++)
{
int max[10] = {0};
int tmp[10] = {0};
for (int j = 0; j < cost.size(); j++)
{
int idx = j + 1;
int val = cost[j];
/*
#ifdef _DEBUG
cout << "i: " << i << " val: " << val << " i - val :" << i - val << " dp[i-val][0]: " << dp[i - val][0] << endl;
#endif*/
if (val \leq i && dp[i - val][0] == -1)
{
// 这里就是可以选
for (int k = 0; k < 10; k++)
{
tmp[k] = dp[i - val][k];
}
tmp[idx]++;

bool swap = true;
int cnt1, cnt2;
cnt1 = cnt2 = 0;

#ifdef _DEBUG
cout << "target: " << target << " i: " << i << " j: " << j << " val: " << val << endl;
for (int t = 1; t \leq 9; t++)
{
cout << tmp[t] << " ";
}
cout << endl;
#endif
// 比较决定选还是不选
for (int k = 9; k >= 1; k--)
{
cnt1 += max[k];
cnt2 += tmp[k];
#ifdef _DEBUG
cout << "max[k]: " << max[k] << " tmp[k]: " << tmp[k] << " cnt1: " << cnt1 << " cnt2: " << cnt2 << endl;
#endif
}

#ifdef _DEBUG

cout << "cnt1: " << cnt1 << " cnt2: " << cnt2 << endl;
#endif

if (cnt1 > cnt2)
{
swap = false;
}
else if (cnt1 < cnt2)
{
swap = true;
}
else if (cnt1 == cnt2)
{
for (int k = 9; k >= 1; k--)
{
cnt1 += max[k];
cnt2 += tmp[k];
if (max[k] > tmp[k])
{
swap = false;
break;
}
else if (max[k] < tmp[k])
{
break;
}
}
}
if (swap)
{
for (int k = 0; k < 10; k++)
{
max[k] = tmp[k];
}
}
dp[i][0] = -1;
}
}
for (int k = 1; k < 10; k++)
{
dp[i][k] = max[k];
}
#ifdef _DEBUG
cout << " i: " << i << endl;
for (int t = 1; t \leq 9; t++)
{
cout << tmp[t] << " ";
}
cout << endl;
cout << endl;
#endif
}
string ret = "";
for (int k = 9; k >= 1; k--)
{
int cnt = dp[target][k];
for (int r = 0; r < cnt; r++)
{
ret += ('0' + k);
}
}
if (ret == "")
{
ret += "0";
}
return ret;
}
};

// for test
int main()
{
Solution s;
vector<int> t1{4, 3, 2, 5, 6, 7, 2, 5, 5};
cout << s.largestNumber(t1, 9) << endl;

return 0;
}

作者

Yu Leng

发布于

2021-06-16

更新于

2024-10-28

许可协议

评论