codeforces 158E Phone Talks (dp)

题意:

麦克是个名人每天都要接n电话,每通电话给出打来的时间和持续时间,麦克可以选择接或不接,但是只能不接k通电话。如果某通电话打来时麦克正在打电话他可以选择让电话排队,或者忽略不接。当麦克空闲时首先从排队的第一个打来的电话开始接起。麦克是个很懒的人,所以需要大量的睡觉,但是睡觉的时间必须是连续的,因此要求出麦克能睡觉的最大连续时间。

题解:

一开状态想错了,想成了dp[i][j][2]前i个电话接j个电话0 1 分别表示这通电话接还是不接。

正确dp[i][j]表示前i通电话放弃了j通的最早结束电话的时间,然后在定义一个ans变量时刻更行最大的的中间空闲的时间。

最后用一天最迟的时间减去dp[n][j]和ans比较得出最大连续睡觉时间。


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long lld;
const int oo=0x3f3f3f3f;
const lld OO=1e18;
const int Mod=1000000007;
const int maxn=4005;
int ans,dp[maxn][maxn];
int t[maxn],d[maxn];

int main()
{
    int n,k;
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d %d",&t[i],&d[i]);
        memset(dp,0x3f,sizeof dp);
        dp[0][0]=1;
        ans=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<=k;j++)
            {
                if(j!=k)
                    dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]);
                if(dp[i][j]<t[i+1])
                {
                    ans=max(t[i+1]-dp[i][j],ans);
                    dp[i+1][j]=min(dp[i+1][j],t[i+1]+d[i+1]);
                }
                else
                    dp[i+1][j]=min(dp[i+1][j],dp[i][j]+d[i+1]);
            }
        }
        for(int i=0;i<=k;i++)
            ans=max(ans,86401-dp[n][i]);
        printf("%d\n",ans);
    }
    return 0;
}





你可能感兴趣的:(codeforces 158E Phone Talks (dp))