HDOJ 4128 Help-or-else(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;

}

你可能感兴趣的:(help)