递推DP UVA 607 Scheduling Lectures

题目传送门

题意:教授给学生上课,有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;
}

  

上一篇:linux – 这些ANSI艺术品使用什么类型的编码?


下一篇:递推DP URAL 1119 Metro