可以套用01背包问题,参考学习资料:【动态规划】01背包问题 - 弗兰克的猫 - 博客园
这道题中,输入的数字的值既是它的weight,也是它的value,背包限重是M,背包所装价值(选中数字value的总值)等于背包的重量(数字weight的总值),因此最后可以用dp[N][M]是否为M来判断有没有解,如果没有解的话,即背包限重装不满,价值达不到M。
之前也做到过动态规划的题,但遇到这题还是不会,学习算法和修改代码花了很多时间 (泪
代码参考:1068. Find More Coins (30)-PAT甲级真题(01背包)_柳婼 の blog-CSDN博客
参考代码里对输入的数字进行了从大到小的排序,并且用choice数组存储所有可能选取的数字,目的是为了满足输出smallest解。
从大到小排序:确定有解后从i=N处回溯,确保每次选取的都是较小数。
用choice数组存储所有可能:确保在dp[i - 1][j - value[i]] + value[i] = dp[i - 1][j]的情况下,数字i可以在回溯时被选取。
个人代码和参考代码有一点不同,在于对于dp数组的定义,参考代码更简洁。
个人代码:
#include#include #include using namespace std; int dp[10001][101] = { 0 }; int choice[10001][101] = { 0 }; int value[10001]; vector result; bool compare(int a, int b) { return a > b; } int main() { int N, M; cin >> N >> M; for (int i = 1; i <= N; i++) cin >> value[i]; sort(value + 1, value + N + 1,compare); for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { if (value[i] > j) dp[i][j] = dp[i - 1][j]; else { if (dp[i - 1][j - value[i]] + value[i] >= dp[i - 1][j]) { choice[i][j] = 1; dp[i][j] = dp[i - 1][j - value[i]] + value[i]; } else dp[i][j] = dp[i - 1][j]; } } } if (dp[N][M] != M) { cout << "No Solution"; return 0; } int i = N, j = M; while (j>0) { if (choice[i][j] == 1) { result.push_back(value[i]); j -= value[i]; i--; } else i--; } for(int i = 0; i



