uva 607(DP+贪心)

简单描述一下题意:有n个topic需要在长度为L的讲座若干个中讲完,每个topic耗费时间为ti, topic必须按顺序讲否则学生听不懂,这样每次讲座会剩余一些时间,最好在10分钟以内,讲座的不满意指数计算如下:

    DI = -c       (1<=t<=10)

       (t-10)*(t-10) (t>10)

       0       (t=0)

t为讲座剩余时间,讲座不能超出时间。要求输出最少要多少个讲座和在相同讲座下最小的DI。

1<=n<=1000 1<=L<=500

题目比较水三重循环也能过,仔细读题后发现最少讲座数是可以根据贪心方法求解的,然后再根据讲座数DP求解最小DI。

dp[i][j] = min(dp[i][j], dp[k][j-1]+DI(cost(k+1, j))))   0 <= k < i

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define maxn 1010
 5 using namespace std;
 6 
 7 int n, l, c, t[maxn], sum[maxn], cnt = 1, ans, dp[maxn][maxn];
 8 
 9 int DI(int time)
10 {
11     if(time>l) return 0;
12     else if(time==l) return 0;
13     else if(l-time<=10) return -c;
14     else return ((l-time)-10)*((l-time)-10);
15 }
16 
17 void solve()
18 {
19     //贪心求最优解
20     int start = 1;
21     for(int i=1; i<=n; i++){
22         if((sum[i]-sum[start-1])>l){
23             start = i;
24             ans++;
25         }
26     }
27     //dp最小DI
28     for(int i=0; i<=ans; i++) dp[0][i] = 0;
29     for(int i=1; i<=n; i++){
30         for(int j=1; j<=ans; j++){
31             for(int k=i-1; k>=0; k--){
32                 if((sum[i]-sum[k])<=l)
33                     dp[i][j] = min(dp[i][j], dp[k][j-1]+DI(sum[i]-sum[k]));
34                 else break;
35             }
36         }
37     }
38 
39 }
40 
41 void debug()
42 {
43     for(int i=0; i<=n; i++){
44         for(int j=0; j<=ans; j++){
45             cout << dp[i][j] << '	';
46         }
47         cout << endl;
48     }
49     cout << endl;
50 
51 }
52 
53 int main()
54 {
55 //    freopen("in.txt", "r", stdin);
56 //    freopen("out.txt", "w", stdout);
57 
58     while(scanf("%d", &n)!=EOF && n)
59     {
60         if(cnt!=1) printf("
");
61         //input
62         scanf("%d%d", &l, &c);
63         sum[0] = 0;ans = 1;
64         memset(dp, 0x7f, sizeof dp);
65         for(int i=1; i<=n; i++){
66             scanf("%d", &t[i]);
67             sum[i] = sum[i-1]+t[i];
68         }
69         solve();
70         //debug();
71         //output
72         printf("Case %d:
", cnt++);
73         printf("Minimum number of lectures: %d
", ans);
74         printf("Total dissatisfaction index: %d
", dp[n][ans]);
75     }
76     return 0;
77 }
View Code
奔跑吧!少年!趁着你还年轻
原文地址:https://www.cnblogs.com/shu-xiaohao/p/3369300.html