poj 3661(区间dp)

来源:互联网 发布:网络驱动器重启后没了 编辑:程序博客网 时间:2024/05/16 14:17

The cows are trying to become better athletes, so Bessie is running on a track for exactly N (1 ≤ N ≤ 10,000) minutes. During each minute, she can choose to either run or rest for the whole minute.
The ultimate distance Bessie runs, though, depends on her ‘exhaustion factor’, which starts at 0. When she chooses to run in minute i, she will run exactly a distance of Di (1 ≤ Di ≤ 1,000) and her exhaustion factor will increase by 1 – but must never be allowed to exceed M (1 ≤ M ≤ 500). If she chooses to rest, her exhaustion factor will decrease by 1 for each minute she rests. She cannot commence running again until her exhaustion factor reaches 0. At that point, she can choose to run or rest.
At the end of the N minute workout, Bessie’s exaustion factor must be exactly 0, or she will not have enough energy left for the rest of the day.
Find the maximal distance Bessie can run.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 contains the single integer: Di
Output
* Line 1: A single integer representing the largest distance Bessie can run while satisfying the conditions.
 
Sample Input
5 2
5
3
4
2
10
Sample Output
9
题目大意:一个人在跑步,总过程为n分钟,第i分钟如果这个人在跑步(没有休息)那么他跑的距离为Di,同时他的疲劳值会加1(第0分钟时疲劳值为0),疲劳值不能超过m,如果这个人第i分钟选择休息,那么每休息一分钟疲劳值便减少1,但是,一旦选择休息,这个哥们要休息到疲劳值为0才会继续行动(休息?让你休息个够)。n分钟过后,这个人的疲劳值必须为0,问n分钟最多能跑多少米。
很明显这是一道dp的问题,官方题解的描述是“This is a straightforward dynamic programming problem”……我们可以定义dp[i][j]为第i分钟过后疲劳值为j时能移动的最大距离,接下来就是思考状态转移方程。
如果j!=0,这种状态很好理解,这说明在第i分钟之内这个人一定在跑步,很容易得出dp[i][j]=dp[i-1][j-1]+D[i]。
如果j==0,显然这要分情况讨论,第i分钟内j有无变化是两种完全不同的情况(!!!),若i分钟内j无变化,说明i-1分钟后,j==0,此时dp[i][j]=dp[i-1][j],相当于这一分钟内这个人什么都没干,若有变化,说明j==0是由前面的某个时刻开始休息然后休息到j==0的,这里就能体现区间dp的思想了,这个“某个时刻”我们并不知道,所以需要向前切割区间寻找最大的距离点,具体见代码。
AC代码:

 #include <iostream>#include <string>#include <cstring>#include <iomanip>#include <cmath>#include <cstdio>#include <algorithm>#include <map>#include <queue>using namespace std;#define ll long long#define maxn 10001#define angel 0x3f3f3f3f#define mod 10007int n,m,maxx[maxn],length[maxn],dp[maxn][501];int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        scanf("%d",&length[i]);    dp[0][0]=0;    dp[1][0]=0;    memset(maxx,-1,sizeof(maxx));    for(int i=1;i<=n;i++)    {        for(int j=0;j<=i&&j<=m;j++)        {            if(i==1&&j==0)                continue;            if(i==n&&j>0)                break;            if(j==0)            {                dp[i][j]=dp[i-1][0];                for(int k=1;i-k>=k&&k<=m;k++)                    dp[i][j]=max(dp[i][j],dp[i-k][k]);            }            else                dp[i][j]=dp[i-1][j-1]+length[i];        }    }    printf("%d\n",dp[n][0]);    return 0;}   
原创粉丝点击