景中人

题目

1354114-20181127082027649-1294825261.png
1354114-20181127082109942-1766957526.png

题解

先将横坐标离散化,下文提到的横坐标都是离散化后的值。

接着考虑dp

\(dp_{i, j}\)表示横坐标为\(i\)\(j\)区间内的答案。
于是有两种转移

  1. 找一个横坐标, 使得没有任意一个矩形穿过它, 枚举转移即可。
  2. 找一个不到横坐标,使得没有任意一个矩形, 那么直接选横坐标范围为[i,j]的矩形,于是把这个矩形的高度设到最高即可\((\)以我的语文水平可能描述的不是很清楚, 具体看代码\()\)

代码

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>

using namespace std;


const int INF = 0x7F7F7F7F;


const int N = 110;


int x[N], y[N];

int maxy[N];

int num[N], total;

int f[N][N], d[N];


int main()
{
    int T;
    
    scanf("%d", &T);
    
    while (T--)
    {
        int n, s;
        scanf("%d %d", &n, &s);
        
        for (int i = 1; i <= n; i++)
            scanf("%d %d", &x[i], &y[i]);
        
        total = 0;
        for (int i = 1; i <= n; i++) num[++total] = x[i];
        sort(num + 1, num + 1 + total);
        total = unique(num + 1, num + 1 + total) - num - 1;
        for (int i = 1; i <= n; i++) x[i] = lower_bound(num + 1, num + 1 + total, x[i]) - num;
        memset(maxy, 0, sizeof(int) * (total + 1));
        for (int i = 1; i <= n; i++) maxy[x[i]] = max(maxy[x[i]], y[i]);
        
        for (int i = 1; i <= total; i++)
            for (int j = 1; j + i - 1 <= total; j++)
            {
                f[j][j + i - 1] = INF;
                int maxh = 0;
                for (int k = j; k <= i + j - 1; k++) maxh = max(maxh, maxy[k]);
                for (int k = j; k < i + j - 1; k++)
                    f[j][j + i - 1] = min(f[j][j + i - 1], f[j][k] + f[k + 1][j + i - 1]);
                
                if ((num[j + i - 1] - num[j]) <= s / maxh) { f[j][j + i - 1] = 1; continue; }
                
                memset(d, 127, sizeof(d));
                int lim = s / (num[j + i - 1] - num[j]);
                d[j - 1] = 0;
                for (int k = j; k <= j + i - 1; k++)
                {   if (maxy[k] <= lim) d[k] = d[k - 1];
                    else for (int l = j; l <= k; l++) d[k] = min(d[k], f[l][k] + d[l - 1]);
                }
                
                f[j][j + i - 1] = min(f[j][j + i - 1], d[j + i - 1] + 1);   
            }
        
        printf("%d\n", f[1][total]);
    }
    
    return 0;
}

转载于:https://www.cnblogs.com/2016gdgzoi509/p/10024320.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值