HDU 4381 Grid 简单DP

http://acm.hdu.edu.cn/showproblem.php?pid=4381

1 ai xi :You can choose any xi black boxes in interval [1,ai], and color them white;
2 ai xi :You can choose any xi black boxes in interval [ai,n], and color them white;

就是给你m个这两种操作,每个操作你可以选做或者不做,还可以选择操作的先后顺序,问最多可以有多少格变成白色


对两种操作分开来看

以第一种操作为例,仔细观察一下,可以得出一个贪心的结论,对操作按ai从小到大排个序之后,对于每一个操作,假如我要使用它,那应该尽可能的先对最左边的可color的格子变色白色,这样保证不会更差。这样的话就可以利用一个类似背包的DP计算出将左边1...j个全部变成白色有需要的最少操作数


对于第二种操作也是同理,最后将两个DP值合并一下就是了。

#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(),(a).end()
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define FORD(i,a,b) for (int i=(a); i>=(b); i--)
#define REP(i,b) FOR(i,0,b)
#define sf scanf
#define pf printf
#define Maxn 1010
using namespace std;
const int maxint = -1u>>1;
const int inf = 1<<29;
const double pi = 3.14159265358979323;
const double eps = 1e-8;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<int>::iterator vit;

int n, m;
pii op1[Maxn], op2[Maxn];
int n1, n2;
int dpl[Maxn], dpr[Maxn];
bool cmp2(pii a, pii b) {
    return a.fi > b.fi || (a.fi == b.fi && a.se < b.se);
}
void init_dp() {
    REP(j, n+2)
        dpl[j] = dpr[j] = inf;

    sort(op1+1, op1+n1+1);
    dpl[0] = 0;
    FOR(i, 1, n1+1) {
        FORD(j, op1[i].fi, op1[i].se)
            dpl[j] = min(dpl[j], dpl[j-op1[i].se] + 1);
    }
    sort(op2+1, op2+n2+1, cmp2);
    dpr[n+1] = 0;
    FOR(i, 1, n2+1) {
        FOR(j, op2[i].fi, n-op2[i].se+2)
            dpr[j] = min(dpr[j], dpr[j+op2[i].se] + 1);
    }
}
int main() {
    int T, ca = 0, type, a, b;
    sf("%d", &T);
    while (T--) {
        sf("%d%d", &n, &m);
        n1 = n2 = 0;
        REP(i, m) {
            sf("%d%d%d", &type, &a, &b);
            if (type == 1) op1[++n1] = mp(a, b);
            else op2[++n2] = mp(a, b);
        }
        init_dp();
        int ans1 = 0, ans2 = inf;
        REP(i, n+1)
            FOR(j, i+1, n+2) {
                if (dpl[i] != inf && dpr[j] != inf) {
                    if (i + n + 1 - j > ans1) ans1 = i + n + 1 - j, ans2 = dpl[i] + dpr[j];
                    else if (i + n + 1 - j == ans1) ans2 = min(ans2, dpl[i] + dpr[j]); 
                }
            }
        if (ans2 == inf) ans2 = 0;
        pf("Case %d: %d %d\n", ++ca, ans1, ans2);
        
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值