Ecust 406 sleeping at work

#include <stdio.h>
#include <memory.h>
int f[510][100],v[510][60];
int a[510];
int max(int a,int b){return a>b?a:b;}
int add(int s,int b);
int main()
{
    int n,k,m,j,i,T,g,maxx,temp;
    scanf("%d",&T);

    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(i=1;i<=n;i++)
        scanf("%d",i+a);
        if((n-n/(k+1))<m)
        {
            printf("impossible\n");
            continue;
        }

        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++)
               for(j=0;j<=k&&j<=i;j++)
                       v[i][j]=add(i,j);
        for(i=1;i<=n;i++)
           for(j=(i>m?m:i);j>=0;j--)
           {
               temp=0;
               for(g=(j>k?k:j);g>=0;g--)
               {
                     if(i==g&&j==g)
                      temp=max(temp,v[i][g]);
                   else if(i==g+1&&j-g>0)
                   {
                    if(j==0)continue;
                    else break;
                   }
                   else
                      temp=max(temp,f[i-g-1][j-g]+v[i][g]);
               }
               f[i][j]=temp;
           }
        maxx=f[1][m];
        for(i=2;i<=n;i++)if(maxx<f[i][m])maxx=f[i][m];
        printf("%d\n",maxx);

    }
    return 0;
}
int add(int s,int b)
{
    int i,j,sum=0;
    for(i=b;i>0;i--)
      sum+=i*a[s+i-b];
    return sum;
}

Sleeping at Work

Time Limit: 4000MS Memory Limit: 100000K
Total Submits: 148 Accepted: 42

Description

You are at work. Unfortunately, there is a programming competition immediately after your working hours. In order to perform well, you need some sleep at work to regain as much energy as possible. Your workday is N minutes long, and each minute has an energy value, e0, e1, ... , eN-1. Your sleep requirement is exactly M minutes, but you can only sleep for a maximum of R minutes in a row before your boss notices. There is a bonus if you sleep for several minutes in a row; the i-th minute in a row will have its energy value multiplied by i. For instance, if you sleep for three minutes having energy values of 10, 10 and 9, you will gain 10 + 2 * 10 + 3 * 9 = 57 energy. After you have slept for M minutes, you are fully rested and cannot sleep any more that day. You have decided to write a computer program which calculates the maximum amount of energy you can gain during a given workday.

Input

The first line of input contains a single integer T, the number of test cases to follow. Each test case begins with a line containing three integer numbers, N, the number of minutes in your workday, M, the sleep requirement in number of minutes, and R, the maximum number of minutes in a row you can sleep before your boss notices. Then follows a line containing N numbers, e0, e1, ... , eN-1, each minute's energy value.

Output

For each test case output one line containing a single number, the highest amount energy that can be gained by sleeping a total of M minutes, or output impossible if it is not possible to get the required amount of sleep.

Sample Input

2
10 3 3
10 10 9 6 5 4 2 1 4 4
10 6 1
1 2 3 4 5 6 7 8 9 10

Sample Output

57
impossible

Hint

  • 0 < T <= 100
  • 0 < N <= 500
  • 0 < M <= 50
  • 0 < R <= 50
  • 0 <= ai < N
  • You can only start and stop sleeping exactly when the minute indicator on the clock changes.

Source

题意:某人要参加编程比赛所以在工作时睡觉补充体力,在所给的工作时间内每个时间点都有一个恢复值,并且连续睡觉时也会有奖励,奖励方式如:连续睡3个时间点,则补充1*a1+2*a2+3*a3; 问在满足睡觉时间内体力恢复的最大值。额,还有一点就是某人的boss会在某人连续睡k个单位时间时发现,前提不能被boss发现。

思路:这是一道很明显的DAG,开始还有点想歪了,突然发觉类似分组的背包。好吧,回到正题来,

       只是简单的一维背包的话肯定不行,因为当前所作的决策不仅仅只由前一状态决定,所以用一个二维数组;

      既然是类似分组的背包,那么我们可以把v[i][j](即第i个时间时已经睡了j个单位时间的补充体力值)作为价值,

     状态则是f[i][j]表示在第i个时间点已经睡了j个单位时间的最大值。

     状态转移方程就和分组背包差不多,但是这个里面的变量值的范围有点绕,在这几乎绕了两个小时,精力还是不够集中啊~

    首先我们可以确定最外层的循环为i[1--n]

         中间那层则是j[min(i,m)--0]随便是不是逆序,理由就不解释了吧。

      最里层的话就是有由k和j确定的 g[min(k,j)--0]这个顺序可以是正向的,只是后面的边界值有所改变而已,另外为什么是min(k,j)了

    因为boss在k时间后会发现他在睡觉,所以只能在某个时间点前睡k个单位时间(包括该时间点),//这个地方wa了几次,后来才发现的

posted on 2011-07-21 12:04  sleeper_qp  阅读(213)  评论(0编辑  收藏  举报

导航