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; }