UVA_607

    我们可以首先预处理出来一节课可以连着上哪些topic,并且这节课的满意度是多少。

    之后用两个数组f[i]、s[i],分别表示一直上到以课程i为结尾的课时的总满意度以及上过的总课时数,动规的过程就像是跳房子,看当前位置可以跳到那个位置,就尝试去更新那个位置。

#include<stdio.h>
#include<string.h>
#define MAXN 1010
#define MAXL 510
#define INF 0x3f3f3f3f
int N, L, C, f[MAXN], t[MAXN], p[MAXN][MAXN], s[MAXN];
int init()
{
int i, j, k, tt, di;
scanf("%d", &N);
if(!N)
return 0;
scanf("%d%d", &L, &C);
for(i = 1; i <= N; i ++)
scanf("%d", &t[i]);
for(i = 1; i <= N; i ++)
for(j = i; j <= N; j ++)
p[i][j] = INF;
for(i = 1; i <= N; i ++)
{
k = 0;
for(j = i; j <= N; j ++)
{
k += t[j];
if(k <= L)
{
tt = L - k;
if(tt == 0)
di = 0;
else if(tt >= 1 && tt <= 10)
di = -C;
else
di = (tt - 10) * (tt - 10);
if(di < p[i][j])
p[i][j] = di;
}
else
break;
}
}
return 1;
}
void solve()
{
int i, j, k;
memset(f, 0x3f, sizeof(f));
memset(s, 0x3f, sizeof(s));
for(i = 1; i <= N; i ++)
if(p[1][i] != INF)
{
s[i] = 1;
f[i] = p[1][i];
}
for(i = 1; i < N; i ++)
if(f[i] != INF)
for(j = i + 1; j <= N; j ++)
{
if(p[i + 1][j] == INF)
break;
if(s[i] + 1 < s[j])
{
s[j] = s[i] + 1;
f[j] = f[i] + p[i + 1][j];
}
else if(s[i] + 1 == s[j] && f[i] + p[i + 1][j] < f[j])
f[j] = f[i] + p[i + 1][j];
}
printf("Minimum number of lectures: %d\n", s[N]);
printf("Total dissatisfaction index: %d\n", f[N]);
}
int main()
{
int x = 0;
while(init())
{
if(x ++)
printf("\n");
printf("Case %d:\n", x);
solve();
}
return 0;
}


posted on 2011-12-06 00:24  Staginner  阅读(307)  评论(0编辑  收藏  举报