题意:每个成绩范围对应一个绩点,给出平均分avg,课程数n,求能得到的平均绩点的最大值和最小值。
思路:先预处理出每个成绩所对应的绩点,然后递推出所有情况,d[i][k]表示i个人有k分的绩点总数,所以可以得到动态转移方程。
当求最大值时d[i][k] = max(d[i][k], d[i - 1][k - j] + gpa[j])(j表示课程分数)
当求最小值时d[i][k] = min(d[i][k], d[i - 1][k - j] + gpa[j])(j表示课程分数)
注意初始化就可以了。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1005; const int INF = 100000.0; double dp1[15][MAXN], dp2[15][MAXN]; double gpa[MAXN]; void init() { for (int i = 60; i <= 69; i++) gpa[i] = 2.0; for (int i = 70; i <= 74; i++) gpa[i] = 2.5; for (int i = 75; i <= 79; i++) gpa[i] = 3.0; for (int i = 80; i <= 84; i++) gpa[i] = 3.5; for (int i = 85; i <= 100; i++) gpa[i] = 4.0; } void solve() { memset(dp1, 0, sizeof(dp1)); for (int i = 60; i <= 100; i++) dp1[1][i] = gpa[i]; for (int i = 2; i <= 10; i++) for (int j = 60; j <= 100; j++) for (int k = j; k <= MAXN; k++) if (dp1[i - 1][k - j] != 0) dp1[i][k] = max(dp1[i][k], dp1[i - 1][k - j] + gpa[j]); for (int i = 0; i <= 10; i++) for (int j = 0; j <= MAXN; j++) dp2[i][j] = INF; for (int i = 60; i <= 100; i++) dp2[1][i] = gpa[i]; for (int i = 2; i <= 10; i++) for (int j = 60; j <= 100; j++) for (int k = j; k <= MAXN; k++) if (dp2[i - 1][k - j] != INF) dp2[i][k] = min(dp2[i][k], dp2[i - 1][k - j] + gpa[j]); } int main() { int cas; scanf("%d", &cas); init(); solve(); while (cas--) { int avg, n; scanf("%d%d", &avg, &n); printf("%.4lf %.4lf\n", dp2[n][avg * n] / n, dp1[n][avg * n] / n); } return 0; }
HDU4968-Improving the GPA,布布扣,bubuko.com
时间: 2024-10-12 22:15:15