bzoj3174: [Tjoi2013]拯救小矮人

被欧老师DDDDDDDDDDDDDDDDDDD飞飞飞飞飞飞飞飞飞飞飞了了了了了了了了了了了了

心态爆炸打打水。。。。贪心啊,玄学啊

就是每次把最挫的挑出来D飞。。。

——————————————————————————————————————————————————————

upd:我以前就是一sb。。。

矮人按a+b的小到大排序

首先假如a1<a2且b1<b2的话,明显尽量让1先跑掉

假如a1+b1<a2或b2,同理也是让1先跑

考虑在剩下的情况中,假设顺序已经排好了,那么假如交换1和2的位置,开始左右的不同部分为a1+b1+a2,b2+a2,后来是a2+b2+a1,b1+a1

假如两个都可能跑掉,那么我们按a+b的小到大排序,更有可能两个跑掉(b2+a2>b1+a1)

否则,先让前一个尝试,失败了再转入后一个状态,也不会亏

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
{
    int x,y;
}a[2100];
bool cmp(node n1,node n2){return (n1.x+n1.y)<(n2.x+n2.y);}

int f[2100];
int main()
{
    int n;
    scanf("%d",&n);
    memset(f,-1,sizeof(f));f[0]=0;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y),f[0]+=a[i].x;
    sort(a+1,a+1+n,cmp);
    
    int H,tot=0;
    scanf("%d",&H);
    for(int i=1;i<=n;i++)
    {
        for(int j=tot;j>=0;j--)
        {
            if(f[j]+a[i].y>=H)f[j+1]=max(f[j+1],f[j]-a[i].x);
            if(f[tot+1]!=-1)tot++;
        }
    }
    printf("%d
",tot);
    return 0;
}

 

原文地址:https://www.cnblogs.com/AKCqhzdy/p/8877320.html