[bzoj3174] 拯救小矮人

题意:N个小矮人被困在了一个高度为h的坑里,每个人都有一定的身高a_i和臂长b_i,小矮人可以站在别人的肩膀上,若a1+a2+...+ak+bk>=h,那么最上面的那个小矮人就可以逃跑,求怎样安排逃跑的顺序,使得尽量多的小矮人逃跑

题解:

贪心+dp

首先按身高加臂长sort(这种有两个代价的题是不是都是这个套路......,并不知道为什么......)

然后dp[i]表示i个人逃跑后剩下人的最大高度,这里好像不需要考虑臂长......,感性理解下就是下面的人越高,那么对上面的人贡献越大,所以出去的人就更多吧......

dp的时候更新最多逃出的人数

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #define ll long long
 8 using namespace std;
 9 
10 const int N = 2010;
11 
12 int dp[N];
13 
14 struct Node {
15   int a,b;
16   bool operator < (const Node &x) const {
17     return a+b<x.a+x.b;
18   }
19 }p[N];
20 
21 int gi() {
22   int x=0,o=1; char ch=getchar();
23   while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
24   if(ch=='-') o=-1,ch=getchar();
25   while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
26   return o*x;
27 }
28 
29 int main() {
30   int n=gi(),h,m;
31   memset(dp,-1,sizeof(dp));
32   dp[0]=0;
33   for(int i=1; i<=n; i++) {
34     p[i].a=gi(),p[i].b=gi();    
35     dp[0]+=p[i].a;
36   }
37   sort(p+1,p+n+1);
38   h=gi(),m=0;
39   for(int i=1; i<=n; i++) {
40     for(int j=m; j>=0; j--) {
41       if(dp[j]+p[i].b>=h) dp[j+1]=max(dp[j+1],dp[j]-p[i].a);
42     }
43     if(dp[m+1]>=0) m++;//dp[m+1]>=0时,一定是在dp[m]+p[i].b满足条件的情况下被转移,所以第j+1个一定可以逃出去
44   }
45   printf("%d
", m);
46   return 0;
47 }
48 //排序,能力强的放在后面,带有贪心的性质?
49 //只需要保证身高最大,不用关心手长?
原文地址:https://www.cnblogs.com/HLXZZ/p/7593733.html