参考文章:http://www.cnblogs.com/kedebug/archive/2012/11/25/2787453.html
题意:
作为一个讲师,有n个知识点要讲。问你最少用要几节课才能把多有知识点讲完,并且在课时最少的情况下,使不满意度最低。
不满意度请看题中所给的公式。
————————————————————————————————————————————————————————
思路:
定义dp[i][j]:前i节课上完j个知识点的最低不满意度。
状态转移:dp[i][j] = min(dp[i][j], dp[i-1][k] + 把第k~j节课都放到第i节课的不满意度);
————————————————————————————————————————————————————————
AC代码:(与参考文章基本一样)
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN = 1005;
const int MAXL = 505;
const int INF = 0x3f3f3f3f;
int dp[MAXN][MAXN];
int sum[MAXN];
int l, c, n;
int res1, res2;
int getDI(int t)
{
if(t == 0) return 0;
if(t > 10) return (t-10)*(t-10);
return -c;
}
void solve()
{
memset(dp, INF, sizeof(dp));
for(int i = 0;i <= n; i++)
dp[i][0] = 0;
//
for(int i = 1;dp[i-1][n] == INF; i++) //if before the i-1 lesson even cover total n topics, don't continue the loop;
{
for(int j = i; j <= n && sum[j] <= i*l; j++)
{
for(int k = j;k >= i-1; k--)
{
if(sum[j] - sum[k] <= l && dp[i-1][k] != INF) //dp[i-1][k] 没有访问过就不应该转移。
{
dp[i][j] = min(dp[i][j], dp[i-1][k] + getDI( l - sum[j] + sum[k]));
}
else if(sum[j] - sum[k] > l)
break;
}
}
}
for(int i = 1;i <= n; i++)
{
if(dp[i][n] != INF)
{
res1 = i;
break;
}
}
//
res2 = dp[res1][n];
}
void output(int& cas)
{
if(cas) puts("");
printf("Case %d:\n", ++cas);
cout<<"Minimum number of lectures: "<<res1<<endl;
cout<<"Total dissatisfaction index: "<<res2<<endl;
}
int main()
{
int cas = 0;
while(scanf("%d", &n), n)
{
cin>>l>>c;
int tmp;
sum[0] = 0;
for(int i = 1;i <= n; i++)
{
cin>>tmp;
sum[i] = sum[i-1] + tmp;
}
solve();
output(cas);
}
return 0;
}