题目
小卖部中有许多种零食,每种零食都有渴望度,且价格小数部分仅可能为0.5或0。一次只能买三包以内的零食,且价格必须是5的整数倍,求能买到的最大渴望度。
具体描述请见hihoCoder。
解题思路
动态规划。递推式:S[i,j,k] = max(S[i-1,j-1,k-m] + s[i],
S[i-1,j,k]),其中i代表零食编号,j代表购买数量,k代表总价格乘2模10。m代表s[i]*2
mod 10。
时间复杂度
时间复杂度为4*10*N,空间复杂度为4*10*N,空间复杂度可优化成4*10*2,更进一步可优化成4*10*1(考虑到递推关系中每次变化仅相差1)。
代码
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
| #include <iostream> #include <algorithm> using namespace std;
int mod(float p) { return (int) (p * 2) % 10; }
int maxSat(float *A, int *B, int N) { int ***S = new int**[N]; for (int i = 0; i < N; i++) { S[i] = new int*[4]; for (int j = 0; j < 4; j++) { S[i][j] = new int[10]; for (int k = 0; k < 10; k++) S[i][j][k] = -1; S[i][0][0] = 0; } }
S[0][1][mod(A[0])] = B[0]; for (int i = 1; i < N; i++) { for (int j = 1; j < 4; j++) { for (int k = 0; k < 10; k++) { int m = (k - mod(A[i]) + 10) % 10; if (S[i - 1][j - 1][m] != -1) S[i][j][k] = S[i - 1][j - 1][m] + B[i]; if (S[i - 1][j][k] != -1) S[i][j][k] = max(S[i][j][k], S[i - 1][j][k]); } } }
int maxS = 0; for (int i = 0; i < 4; i++) maxS = max(maxS, S[N - 1][i][0]);
for (int i = 1; i < N; i++) { for (int j = 1; j < 4; j++) delete[] S[i][j]; delete[] S[i]; } delete[] S;
return maxS; }
int main() { int Q = 0; cin >> Q; for (int i = 0; i < Q; i++) { int N = 0; cin >> N; float *A = new float[N]; int *B = new int[N]; for (int j = 0; j < N; j++) cin >> A[j] >> B[j];
cout << maxSat(A, B, N) << endl;
delete[] A, B; }
return 0; }
|