题意:教授给学生上课,有n个主题,每个主题有ti时间,上课有两个限制:1. 每个主题只能在一节课内讲完,不能分开在多节课;2. 必须按主题顺序讲,不能打乱。一节课L时间,如果提前下课了,按照时间多少,学生会有不满意度。问最少要几节课讲完主题,如果多种方案输出不满意度最小的
分析:dp[i]表示前i个主题最少要多少节课讲完,那么这个主题可能和上个主题在同一节课讲或者多开新的一节课讲,状态转移方程:看代码;优先满足节数少的情况
收获:普通的递推DP
代码:
/************************************************ * Author :Running_Time * Created Time :2015-8-29 15:48:09 * File Name :UVA_607.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int N = 1e3 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int dp[N], d[N], a[N]; int n, L, C; int get_DI(int x) { if (!x) return 0; if (1 <= x && x <= 10) return -C; else return (x - 10) * (x - 10); } int main(void) { int cas = 0; while (scanf ("%d", &n) == 1) { if (!n) break; scanf ("%d%d", &L, &C); for (int i=1; i<=n; ++i) scanf ("%d", &a[i]); dp[0] = d[0] = a[0] = 0; for (int i=1; i<=n; ++i) { dp[i] = dp[i-1] + 1; d[i] = d[i-1] + get_DI (L - a[i]); int cur = 0; for (int j=i; j>=1; --j) { cur += a[j]; if (cur > L) break; if (dp[j-1] + 1 < dp[i] || (dp[j-1] + 1 == dp[i] && d[j-1] + get_DI (L - cur) < d[i])) { dp[i] = dp[j-1] + 1; d[i] = d[j-1] + get_DI (L - cur); } } } if (cas) puts (""); printf ("Case %d:\n", ++cas); printf ("Minimum number of lectures: %d\n", dp[n]); printf ("Total dissatisfaction index: %d\n", d[n]); } return 0; }
时间: 2024-11-05 14:24:20