LuoguP4823 [TJOI2013]拯救小矮人
LuoguP4823 [TJOI2013]拯救小矮人
Description
题目大意:n个人每个人有身长A和臂长B,如果满足A1+A2+……An+Bn>=H 则第N个人可以爬出洞
怎样安排顺序使最多人爬出洞。
Solution
可以考虑一个显然的贪心:身高+臂长越长的人越后面出去
所以按身高加臂长排序,让越难出去的先出去。
但是因为出去是由身高加臂长两个因素决定的
所以不代表身高加臂长长的人一定在小的人后出去
举个例子,当H=9 如果a1 = 5 , b1 = 2 ,a2 = 2 ,b2 = 1
那么反而要身高加腿长更小的当人梯
即需要考虑奉献自己的情况
所以考虑DP
令DP[i]表示前面更容易走的走了i个人后剩下的最大高度
转移方程见代码
#include<bits/stdc++.h> using namespace std; inline int read() { int f = 1 ,x = 0; char ch; do { ch = getchar(); if(ch == '-') f = -1; }while(ch<'0'||ch>'9'); do { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch>='0'&&ch<='9'); return f*x; } const int MAXN = 100000 + 10; struct ZHENGJUNSHIDASHABI { int a; int b; friend bool operator < (ZHENGJUNSHIDASHABI a1,ZHENGJUNSHIDASHABI a2) { if(a1.a+a1.b == a2.a + a2.b) return a1.a<a2.a; else return a1.a+a1.b<a2.a+a2.b; } }p[MAXN]; int n; int H; int dp[MAXN]; int main() { n = read(); for(int i=1;i<=n;i++) p[i].a = read(),p[i].b = read(),dp[0]+=p[i].a; sort(p+1,p+n+1); H = read(); for(int i=1;i<=n;i++) dp[i] = -(1<<30); for(int i=1;i<=n;i++) { for(int j=i;j>=1;j--) { if(dp[j-1] + p[i].b >= H) { dp[j] = max(dp[j] , dp[j-1] - p[i].a); } } } int res = 0; for(int i=n;i>=0;i--) if(dp[i] >= 0){res = i;break;} cout << res << endl; }