1. 程式人生 > 實用技巧 >LuoguP4823 [TJOI2013]拯救小矮人

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