解题报告: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(nlog 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
",ans);
	return 0; 
}
原文地址:https://www.cnblogs.com/tlx-blog/p/12684951.html