解题报告:AT3605
题目链接:AT3605 Zabuton
首先有一个很相似的题:P3619 魔法
有这个题的经验,可以知道要按 \(h_i+p_i\) 排序。
感性理解一下,这个值就是最远到达的距离。
为什么这么想?
首先考虑 \(dp\)。
由于我们没有选择的顺序,而限制条件是有顺序的,比如两个人先选某一个结果不同。
考虑确定顺序,那么我们就联想到排序。
剩下的就是推方程了。
考虑如何记录前面的状态。
显然只需记录选了几个就好了,即记 \(dp[i]\) 为前 \(i\) 个最少有多少砖。
为什么?我也不知道
由于前面的状态对后面有影响的只是总砖数,那么记录下了就好了。
很容易得到方程:
\[dp[j]=(dp[j-1]\leqslant h_i)min\{dp[j-1]+p_i\}
\]
唉,这不是背包吗?
时间复杂度为 \(\mathcal O(n\log n+n^2)\),可以通过本题。
如此优秀的一道题,可惜我不会做,在大佬帮助下才通过了此题。
\(Code\):
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define read(x) scanf("%lld",&x)
#define MAXN 5005
#define ll long long
#define inf 0x7fffffffffffffff
int n;
struct node
{
ll h,p;
}a[MAXN];
ll dp[MAXN];
int ans;
bool cmp(node x,node y){return x.h+x.p<y.h+y.p;}
int main()
{
read(n);
for(int i=1;i<=n;i++) read(a[i].h),read(a[i].p);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) dp[i]=inf;
dp[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=i;j>=1;j--) if(dp[j-1]<=a[i].h) dp[j]=min(dp[j],dp[j-1]+a[i].p);
}
for(int i=0;i<=n;i++) if(dp[i]<inf) ans=i;
printf("%d\n",ans);
return 0;
}