题意:
给出一节课的时长l以及不满意计算值c,给出n个主题的时长,求怎样安排主题最后的不满意度最低
思路:
首先计算到i个主题所耗费时间,存在sum里面,用于之后计算一节课占用时间
枚举节数,枚举到此节所能涵盖的知识点数,枚举上节课涵盖的知识点数
那么这节课的不满意度可由sum[j]-sum[k](第i节用时)算出
当然节数和可涵盖的知识点数从小到大,这样才能保证利用之前计算出的结果
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<climits>
#include<cstdlib>
using namespace std;
const int maxn = 1010;
int dp[maxn][maxn];
int a[maxn], sum[maxn];
int l, c;
int get(int x) {
int u = l-x;
if(u==0) return 0;
if(u>0 && u<=10) return -c;
if(u > 10) return (u-10) * (u-10);
}
int main() {
int n;
int cases = 0;
while(scanf("%d", &n) && n) {
memset(sum, 0, sizeof(sum));
scanf("%d%d", &l, &c);
for(int i=1; i<=n; i++)
scanf("%d", &a[i]), sum[i] = sum[i-1] + a[i];
for(int i=0; i<=n; i++) {
dp[i][0] = 0;
for(int j=1; j<=n; j++)
dp[i][j] = INT_MAX;
}
for(int i=1; dp[i-1][n]==INT_MAX; i++)
for(int j=i; j<=n && sum[j] <= l*i; j++) //枚举可以涵盖的主题
for(int k=j; k>=i-1; k--) {//枚举上节课覆盖的主题
if(sum[j]-sum[k] <= l && dp[i-1][k] != INT_MAX) {
dp[i][j] = min(dp[i][j], dp[i-1][k]+get(sum[j]-sum[k]));
}
else if(sum[j] - sum[k] > l)break;//上节课的涵盖量太小
}
int i;
for( i=1; i<=n; i++) if(dp[i][n] != INT_MAX) break;
if (cases)
printf("\n");
printf("Case %d:\n", ++cases);
printf("Minimum number of lectures: %d\n", i);
printf("Total dissatisfaction index: %d\n", dp[i][n]);
}
return 0;
}