比较简单的一道题目,按照动态规划的思想,dp[i][j]代表i位数模m的结果为j的所使用的最少火柴的个数。注意在找结果的过程当中我们是从高位向低位进行查找的,同时注意我们在最后查找结果的过程当中终止条件是i>0,这是因为位数不可能为0。具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
int n, m;
int dp[55][3010];
int remain[55];
int record[] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
void dfs(int length, int number){
if (length == 0){
cout << endl;
return;
}
for (int i = 9; i >= 0; i--){
int new_n = (number - ((remain[length-1] * i) % m) + m) % m;
if (dp[length - 1][new_n] + record[i] <= n){
cout << i;
n -= record[i];
dfs(length - 1, new_n);
return;
}
}
}
int main(){
int Case = 0;
while (cin >> n&&n){
cin >> m;
cout << "Case " << ++Case << ": ";
remain[0] = 1;
for (int i = 1; i < 55; i++){
remain[i] = (remain[i - 1] * 10) % m;
}
for (int i = 0; i <= n / 2; i++){
for (int j = 0; j < m; j++) dp[i][j] = 1 << 30;
}
dp[0][0] = 0;
for (int i = 0; i < n / 2; i++){
for (int j = 0; j < m; j++){
if (dp[i][j] != 1 << 30){
int d = dp[i][j];
for (int num = 0; num <= 9; num++){
dp[i + 1][(j * 10 + num) % m] = min(dp[i + 1][(j * 10 + num) % m], d + record[num]);
}
}
}
}
int result = -1;
for (int i = n / 2; i > 0; i--){
if (dp[i][0] != 1 << 30 && dp[i][0] <= n){
result = i;
break;
}
}
if (result == -1){
cout << result << endl;
}
else{
dfs(result,0);
}
}
return 0;
}