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
Output
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 阅读(221) 评论(0) 收藏 举报
浙公网安备 33010602011771号