2 20 10 5 5 30 2 20 10 5 5 35
2 1HintFor the first case, the tall dwarf can help the other dwarf escape at first. For the second case, only the tall dwarf can escape.
dp[i][j]代表由大到小排序后,前i人中能逃脱j人需要之前的人留在井中的高度和。
每一次必然是身高和臂长和短的人先逃出去,dp[i][j]只可能由两种情况得来:
dp[i-1][j]:代表i位置的人没出去,所以所需的高度就是dp[i-1][j] - a[i]。
dp[i-1][j-1]:代表i位置的人出去了,所需高度有两种情况:
1. i的身高和臂长之和足够大,利用之前所需高度就可以逃脱,这是所需高度是dp[i-1][j-1]。
2. i的身高和臂长之和不够大,因为每一次必然是短的人先出去,而排序后i的长度必然最短,所以需要的高度就是后i-1个人帮助i逃脱,所需高度是H - sumA[i] - b[i]。
这两种情况要取最大值。
综上所述,最终的递推公式就是:
dp[i][j] = min(dp[i-1][j] - a[i], max(dp[i-1][j-1], H - sumA[i] - b[i]);
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int mm=2e3+9; class node { public: int a,b; bool operator<(const node&x)const { return a+b>x.a+x.b; } } f[mm]; int dp[mm][mm],n,suma[mm]; int main() { int hh; while(~scanf("%d",&n)) { suma[0]=0; for(int i=1; i<=n; ++i) { scanf("%d%d",&f[i].a,&f[i].b); } scanf("%d",&hh); sort(f+1,f+n+1); for(int i=1; i<=n; ++i) { suma[i]=suma[i-1]+f[i].a; } ///memset(dp,0,sizeof(dp)); dp[0][0]=0; for(int i=0; i<=n; ++i) for(int j=i+1; j<=n; ++j) dp[i][j]=1e9; for(int i=1; i<=n; ++i) ///前i个人出j个需要留下的最小长度 for(int j=0; j<=i; ++j) { dp[i][j]=dp[i-1][j]-f[i].a; if(j) dp[i][j]=min(dp[i][j],max(dp[i-1][j-1],hh-suma[i]-f[i].b)); } /// for(int i=0;i<=n;++i) //cout<<" "<<dp[n][i]<<" ";puts(""); for(int i=n; i>=0; --i) if(dp[n][i]<=0) { printf("%d\n",i); break; } } return 0; }