• BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP


    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    Description

    一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯。即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口。对于每一个小矮人,我们知道他从脚到肩膀的高度Ai,并且他的胳膊长度为Bi。陷阱深度为H。如果我 们利用矮人1,矮人2,矮人3,。。。矮人k搭一个梯子,满足A1+A2+A3+....+Ak+Bk>=H,那么矮人k就可以离开陷阱逃跑了,一 旦一个矮人逃跑了,他就不能再搭人梯了。
    我们希望尽可能多的小矮人逃跑, 问最多可以使多少个小矮人逃跑。

    Input

    第一行一个整数N, 表示矮人的个数,接下来N行每一行两个整数Ai和Bi,最后一行是H。(Ai,Bi,H<=10^5)

    Output

    一个整数表示对多可以逃跑多少小矮人

    Sample Input

    样例1

    2
    20 10
    5 5
    30

    样例2
    2
    20 10
    5 5
    35

    Sample Output

    样例1
    2

    样例2
    1

    HINT

    数据范围

    30%的数据 N<=200

    100%的数据 N<=2000


    分析:

    这道题其实是在求一个子序列。在某种方案下都能够逃跑的子序列中最长的一个。

    我们先贪心地确定逃跑方案。

    首先,对于两个一定要逃跑的人x和y,如果a[x]+a[y]<b[x]+b[y],说明x比y弱,不妨让x先逃跑。

    于是我们可以按a+b排一下序。

    然后找最长的子序列。设f[i][j]为前i个人,走了j个后最高的高度。

    f[i][j]=f[i-1][j]; f[i][j]=max(f[i][j],f[i-1][j-1]-a[j])(b[j]+f[i-1][j-1]>=h)

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 2050
    struct A {
    	int a,b;
    }a[N];
    int h,n,f[N][N];
    bool cmp(const A &x,const A &y) {
    	return x.a+x.b<y.a+y.b;
    }
    int main() {
    	scanf("%d",&n);
    	int i, ans=0, j;
    	memset(f,-1,sizeof(f));
    	f[0][0]=0;
    	for(i=1;i<=n;++i) scanf("%d%d",&a[i].a,&a[i].b),f[0][0]+=a[i].a;
    	sort(a+1,a+n+1,cmp);
    	scanf("%d",&h);
    	for(i=0;i<n;++i) {
    		f[i+1][0]=f[i][0];
    		for(j=0;j<=ans;j++) {
    			f[i+1][j+1]=f[i][j+1];
    			if(f[i][j]+a[i+1].b>=h) {
    				f[i+1][j+1]=max(f[i+1][j+1],f[i][j]-a[i+1].a);
    			}
    		}
    		if(f[i+1][ans+1]>=0) ans++;
    	}
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    游戏资源贴
    赠云风大侠
    微软ad域的初步认识
    WAMP 80端口被MicrosoftHTTPAPI/2.0占用的解决办法
    单点登录的一系列尝试及最终解决
    母版页缓存问题
    Vs2012如何创建数据库
    Request.QueryString 不能像使用方法那样使用不可调用
    将textbox中的光标移动到当前输入的文本后
    用户控件学习笔记
  • 原文地址:https://www.cnblogs.com/suika/p/8678271.html
Copyright © 2020-2023  润新知