……

解题报告: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; 
}
posted @ 2020-04-12 13:47  童话镇里的星河  阅读(149)  评论(0编辑  收藏  举报