问题
类似有限背包问题,题目链接:clicker
实现
#include<stdio.h> #include<cmath> #include<iostream> #include<string.h> #include<algorithm> #include<queue> #include<stack> #include<map> #include<deque> #include<string> #include<unordered_map> #include<unordered_set> using namespace std; #define max(a, b) (a) > (b)? (a) : (b) int dp[35][20005]; int A[35]; int B[35]; int main() { int n, m; scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) { scanf("%d %d", &A[i], &B[i]); } memset(dp, 0, sizeof(dp)); //有限背包问题, dp[i][j] 表示对于前i种物品,耗费j时能够得到的最大收益 for (int i = 1; i <= n; i++) { //dp的定义,前i种物品的收益情况,依赖于前i-1种物品的情况。 i表示前i种物品 for (int j = 0; j <= m; j++) { //耗费为j,这里j从小到大枚举和从大到小枚举都行,因为 //根据递推公式: dp[i][j] = max(dp[i][j], dp[i - 1][j - cost] + k*A[i - 1]); dp[i][j] 和 dp[i-1][jj]有关, //而在内层循环的j的枚举方向不会影响结果正确性(如果 dp[i][j] 和 dp[i][jj] (jj为大于或者小于j的数)有关,则会影响) int k = 1; int t = B[i - 1]; int cost = t; dp[i][j] = max(dp[i][j], dp[i - 1][j]); //第i种一个都不要 while (cost <= j) { //依次枚举第i种物品的个数 dp[i][j] = max(dp[i][j], dp[i - 1][j - cost] + k*A[i - 1]); t *= 1.07; cost += int(t); k++; } } } printf("%d ", dp[n][m]); return 0; }