【STSRM10】dp只会看规律

【算法】区间DP

【题意】平面上有n个点(xi,yi),用最少个数的底边在x轴上且面积为S的矩形覆盖这些点(在边界上也算覆盖),n<=100。

【题解】随机大数据下,贪心几乎没有错误,贪心出奇迹啊!

f[i][j][h]表示区间i~j高度>=h的点全部被覆盖的最少矩形。

首先离散化横纵坐标,然后初始化每个f[i][i],然后进行区间DP(顺次枚举区间长度,左端点,高度从大到小)转移如下。

f[i][j][h]=min(f[i][j][h],f[i][x][h]+f[x+1][j][h]),x=i~j-1

h2=s/(x[j]-x[i])(注意离散化)

f[i][j][h]=min(f[i][j][h],f[i][j][h2+1]+1)

为什么这样转移是正确的?

考虑一个区间内情况,有以下两种选择:

1.分成两个区间各自摆矩形并列。

2.在整个区间设置打矩形,则h2部分另外处理。

其它情况?直接在区间摆大矩形覆盖全部等价于第二种情况,大区间h之上只有小区间的点等价于第一种情况,所以一共只有两种情况。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int read()
{
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c==‘-‘)t=-1;
    do{s=s*10+c-‘0‘;}while(isdigit(c=getchar()));
    return s*t;
}
/*------------------------------------------------------------*/
const int inf=0x3f3f3f3f,maxn=110;
struct cyc{int x,y;}a[maxn],b[maxn],c[maxn];
int n,f[maxn][maxn][maxn],ynum[maxn],tot,s;
bool cmp(cyc a,cyc b)
{return a.x<b.x||(a.x==b.x&&a.y>b.y);}
int main()
{
    scanf("%d%d",&n,&s);
    for(int i=1;i<=n;i++){
        a[i].x=read();
        a[i].y=read();
    }
    sort(a+1,a+n+1,cmp);
    int totx=1;
    c[totx]=a[1];
    for(int i=2;i<=n;i++)if(a[i].x!=a[i-1].x)c[++totx]=a[i];
    tot=n=totx;
    for(int i=1;i<=n;i++)a[i]=c[i];
    for(int i=1;i<=n;i++)ynum[i]=a[i].y;
    sort(ynum+1,ynum+tot+1);
    tot=unique(ynum+1,ynum+tot+1)-ynum-1;
    for(int i=1;i<=n;i++){b[i].x=i;b[i].y=lower_bound(ynum+1,ynum+tot+1,a[i].y)-ynum;}
    ynum[++tot]=inf;
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++){for(int k=tot;k>b[i].y;k--)f[i][i][k]=0;for(int k=b[i].y;k>=0;k--)f[i][i][k]=1;}
    for(int p=2;p<=n;p++){
        for(int i=1;i+p-1<=n;i++){
            int j=i+p-1;
            for(int h=tot;h>=0;h--){
                for(int x=i;x<j;x++)f[i][j][h]=min(f[i][j][h],f[i][x][h]+f[x+1][j][h]);
                int h2=lower_bound(ynum+1,ynum+tot+1,s/(a[j].x-a[i].x))-ynum;
                if(ynum[h2]==s/(a[j].x-a[i].x))h2++;
                f[i][j][h]=min(f[i][j][h],f[i][j][h2]+1);
            }
        }
    }
    printf("%d",f[1][n][0]);
    return 0;
}

时间: 2024-10-11 07:36:49

【STSRM10】dp只会看规律的相关文章

HDU 4588 Count The Carries 数位DP || 打表找规律

2013年南京邀请赛的铜牌题...做的很是伤心,另外有两个不太好想到的地方....a 可以等于零,另外a到b的累加和比较大,大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数,然后统一进位. 设最低位为1,次低位为2,依次类推,ans[]表示这一位上有多少个1,那么有 sum += ans[i]/2,ans[i+1] += ans[i]/2; sum即为答案. 好了,现在问题转化成怎么求ans[]了. 打表查规律比较神奇,上图不说话. 打表的代码 #include <algo

学习也好,科研也罢,都有内在规律。任何事物,只消抓住规律,就等于牵住牛鼻子

一个工程技术人员,如果没有把复杂问题简单化能力,将一事无成. 马伟明认为:“学习也好,科研也罢,都有内在规律.任何事物,只消抓住规律,就等于牵住牛鼻子.”高等数学,不管是微分.积分,还是多元函数.微分方程,马伟明用两个字抽象:极限:电学,不论强电还是弱电,马伟明抽象为:正方向:自动控制理论,不管经典的.现代的,还是线性的.非线性的,马伟明以“反馈”概括……他一再告诫学生,“一个工程技术人员,如果没有把复杂问题简单化和本质化的能力,将一事无成.” <就要领先美国:海军马伟明院士说的10句话瞬间击溃

Pycharm新手教程,只需要看这篇就够了

pycharm是一款高效的python IDE工具,它非常强大,且可以跨平台,是新手首选工具!下面我给第一次使用这款软件的朋友做一个简单的使用教程,希望能给你带来帮助! 目前pycharm一共有两个版本,Professional(专业版本)」和「社区版」,专业版功能最强大,主要是为 Python 和 web 开发者而准备,是需要付费的.社区版是专业版的阉割版,比较轻量级,主要是为 Python 和数据专家而准备的.一般我们做开发,下载专业版本比较合适. 文章转自:django中文网---Pych

loj516 「LibreOJ β Round #2」DP 一般看规律

传送门:https://loj.ac/problem/516 [题解] 那段代码求的是相同的数中间隔最小的值. 离散后用set维护每个值出现次数,每次操作相当于合并两个set,这步可以启发式合并. 加元素的时候直接找前驱和后继即可. 学了新姿势:set中insert有返回的,可以访问.first来调用新插入元素的iterator # include <set> # include <vector> # include <stdio.h> # include <st

loj516 DP一般看规律(set启发式合并)

题目: https://loj.ac/problem/516 分析: 每次将一个颜色更改为另一个颜色相当于将两个集合合并 然后对于答案的更新,一个点插入到一个集合中,那么可能更新答案的就是其前驱节点或者后继节点 所以直接用set启发式合并就ok了 时间复杂度O(nlog^2n+m)

系统策略,只允许看,不允许复制--未测试

windows server 2008域中,如何实现禁止从远程桌面中复制文件到远程登陆机中,和禁止上传文件到服务器中 环境:使用2008域服务器,员工的客户端机24小时工作.要求:禁止员工用远程桌面登陆到客户端机中复制文件和禁止粘贴文件到客户端中. 我有更好的答案 通过组策略,我们可以解决以上问题,开始菜单运行输入gpedit.msc,进入“计算机配置”项,按顺序进入“管理模板”.“windows组件”.“终端服务”.“客户端/服务器数据重定向”.在详细描述栏中启用“不允许剪切板重定向”.“不允

loj516dp一般看规律

STL 这...我只能说是...考得是... STL的正确用法? #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<set> #include<m

[SRM] 09 CCZ的诗

QwQ为数不多的几次有部分分的OI赛制的SRM,感谢CCZ的一屋子部分分= = A. 模拟只会猜题意 B. 贪心只能过样例 给出n个数a[i](1<=a[i]<=n),问最多能把这些数分成几组,使得每个数a[i]所在的组至少有a[i]个数 输入格式 第一行一个整数n,接下来n行每行一个整数分别是a[1],a[2],...,a[n] 输出格式 一行,输出答案,一个整数 分析 因为是按组分,所以顺序也就不重要了,先sort成递增 为了保证分组数最多,应该从大到小一个个满足(有点像弹飞绵羊呢) 方程

HDU 5000 Clone 规律+dp 2014 ACM/ICPC Asia Regional Anshan Online

每只羊有n个属性 下面n个数字表示每个属性的值范围为[ 0, T[i] ] 对于羊圈里的a羊和b羊,若a羊的每个属性都>=b羊,则a羊会杀死b羊. 问羊圈里最多存活多少只羊. 规律1:sum相同的羊不会互相杀死. 因为若2个羊的属性都相同,a羊某个属性要增加1,则a羊另一个属性要减少1,这样ab一定能共存. 规律2: sum不同的羊不会重合. 我们设a羊sum = x,b羊sum = y,若a,b羊能共存,但不会把ab同时放到羊圈里. 因为一定存在一只羊c ,sum = x,且c和b不能共存,既