实验目的:
练习动态规划
实验内容:
易老师购买了一盒饼干,盒子中一共有k块饼干,但是数字k有些数位变得模糊了,看不清楚数字具体是多少。易老师需要你帮忙把这k块饼干平分给n个小朋友,易老师保证这盒饼干能平分给n个小朋友。现在需要计算出k有多少种可能的数值。.
输入描述:输入包括两行,第1行为盒子上的数值k,模糊的数位用X表示,长度小于18( 可能有多个模糊的数位),第2行为小朋友的人数n。
输出描述:输出k可能的数值种数,保证至少为1。
输入样例:
9999999999999X
3
样例输出:
4
思路:
动态规划,模拟除法,依次计算前i位除以n余数为j的情况个数,最后前m(k的位数长度)位余0的值即为答案。
举例,74X / 3 ,在手工做除法时,前位余数乘十+下一位当新的被除数。
先做7/3,余1,这时前1位余数为1的情况为1;
之后做 1(之前的余数)*10+4 / 3 ,余2,前2位余数为2的情况为1
之后做 2(之前的余数)*10 + X / 3,这时遍历X的所有取值情况,发现21、24、27(X取1、4、7时) / 3余数为0,有三种
也即是前3位余数为0的情况
代码
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n;
string s;
cin >> s;
cin >> n;
int m = s.size();
vector<vector<int>> dp(m+1, vector<int>(n, 0)); //建一个(m+1)*n的二维数组,初始化为0
dp[0][0] = 1; //初始位为1
int tmp;
for (int i = 1; i <= m; i++) {
for (int j = 0; j < n; j++) { //余数可以为0到n-1
if (s[i - 1] == 'X' && i == 1) { //当前位不确定,且为首位,k不能取0
for (int k = 1; k <= 9; k++) {
tmp = (j * 10 + k) % n;
dp[i][tmp] += dp[i - 1][j];
}
}
else if (s[i - 1] == 'X' && i != 1) { //当前位不确定,且不为首位,k可取0到9
for (int k = 0; k <= 9; k++) {
tmp = (j * 10 + k) % n;
dp[i][tmp] += dp[i - 1][j];
}
}
else { //当前位确定
tmp = (j * 10 + (s[i - 1] - '0')) % n;
dp[i][tmp] += dp[i - 1][j];
}
}
}
cout << dp[m][0] << endl;
return 0;
}
结果截图:
总结:
主要要想通模拟除法的过程