解题思路:本来想用三维数组的,但是题目的n有点大,用不了,如果用三维数组的话,就可以表示为dp[i][j][step] = min (dp[i][j][step],dp[i][k][step-1] + d[k][l]),dp[i][j][step]表示第i小节到第j小节用了step堂课教的不满意度的最小值,d[k][l]表示第k小节到第j小节在同一堂课上上完的不满意度,只要dp[1][n][step]不为INF了,那么就表示用最少堂课上完了所有的小节了,且那个值也是最低的了,但这行不通,三维的话会爆掉,毕竟n <= 1000,既然不能三维的话,就叉开成两个一维的,l[i]表示上到第i小节用了多少堂课,ds[i]表示上到第i小节的不满意度为多少,那么就可以得到转换式子了,if(l[i] + 1 < l[j] ) 那么 l[j] = l[i] + 1,ds[j] = ds[i] + d[i+1][]j,毕竟以课为少为优先的,if(l[i] + 1 == l[j] && ds[i] + ds[i+1][j] < ds[j]),则ds[j] = ds[i] + d[i+1][j]
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 1100
#define INF 0x3f3f3f3f
int dp[maxn][maxn],t[maxn],l[maxn],ds[maxn];
int n, L, C;
void init() {
scanf("%d%d",&L,&C);
for(int i = 1; i <= n; i++)
scanf("%d",&t[i]);
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
dp[i][j] = INF;
int temp,di,tt;
for(int i = 1; i <= n; i++) {
temp = 0;
for(int j = i ; j <= n; j++) {
temp += t[j];
tt = L - temp;
if(temp > L)
break;
if(tt == 0)
dp[i][j] = 0;
else if( tt >= 1 && tt <= 10)
dp[i][j] = -C;
else
dp[i][j] = (tt - 10) * (tt - 10);
}
}
}
void solve() {
memset(ds,0x3f,sizeof(ds));
memset(l,0x3f,sizeof(l));
for(int i = 1;i <= n; i++)
if(dp[1][i] != INF) {
ds[i] = dp[1][i];
l[i] = 1;
}
for(int i = 1 ; i <= n; i++)
for(int j = i + 1; j <= n; j++) {
if(dp[i+1][j] == INF)
break;
if(l[i] + 1 < l[j]) {
l[j] = l[i] + 1;
ds[j] = dp[i+1][j] + ds[i];
}
else if(l[i] + 1 == l[j] && dp[i+1][j] + ds[i] < ds[j])
ds[j] = ds[i] + dp[i+1][j];
}
printf("Minimum number of lectures: %d\n",l[n]);
printf("Total dissatisfaction index: %d\n",ds[n]);
}
int main() {
int mark = 1;
int bo = 1;
while(scanf("%d",&n) != EOF && n) {
if(bo)
bo = 0;
else
printf("\n");
printf("Case %d:\n",mark++);
init();
solve();
}
return 0;
}