HDOJ 4128 Helporelse(DP)

题意:从时间0开始需要接待n个人,对于每个人,可以选择接待或者跳过,若接待,花费的时间是T+ai ,T为开始接待这个人的时间,若跳过则罚时bi ,现给定总时间K,问你最多能接待多少人?
分析:如果接待的人的集合确定了,那你一定先接待 bi 小的人再接待 bi 大的人,所以我们可以先按 b 从小到大排序。定义dp[i][j]表示从 i 到 n 的人共接待 j 个人的花费(i 到 n这一段的花费)。dp[i][j]=min( dp[i+1][j] , dp[i+1][j-1] - a[i] + j*b[i] ),最后从大往小找dp[0][j]不超过K的最大的 j 即是答案。

View Code
#include <stdio.h>
#include <algorithm>
using namespace std;
#define N 201
struct node
{
    int a,b;
    bool operator<(const node &t)    const
    {
        return b<t.b;
    }
};
node t[N];
int n,m;
int dp[N][N];
void dfs(int i)
{
    if(i==n)
    {
        dp[i][0]=t[n].a;
        dp[i][1]=t[n].b;
        return;
    }
    dfs(i+1);
    int j;
    dp[i][0]=dp[i+1][0]+t[i].a;
    for(j=1;j<=n-i;j++)
    {
        dp[i][j]=min(dp[i+1][j]+t[i].a,dp[i+1][j-1]+t[i].b*j);
    }
    dp[i][j]=dp[i+1][j-1]+t[i].b*j;
}
int main()
{
    int ca=0;
    while(scanf("%d%d",&n,&m),(n|m))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&t[i].a,&t[i].b);
        }
        sort(t+1,t+n+1);
        dfs(1);
        int cnt;
        for(cnt=n;cnt>=0 && dp[1][cnt]>m;cnt--);
        printf("%d: ",++ca);
        if(cnt<0) puts("Mission Impossible");
        else    printf("%d\n",cnt);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/algorithms/p/2691018.html