bzoj1766: [Ceoi2009]photo

来源:互联网 发布:软件健壮性 软件可靠性 编辑:程序博客网 时间:2024/05/29 19:36

传送门
跪Claris神犇。
首先得到状态f[i][j][k]表示在i到j的区间内高度大于k的最小矩形数目。
然后就两种转移:分割线或者放尽量大的新矩形。

#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct P{int x,y;}a[105];int n,m,A,b[105],c[105],f[105][105][105];bool cmp(P a,P b){    return a.x==b.x?a.y>b.y:a.x<b.x;}int main(){    scanf("%d%d",&n,&A);    for (int i=1;i<=n;i++)        scanf("%d%d",&a[i].x,&a[i].y);    sort(a+1,a+n+1,cmp);    for (int i=1;i<=n;i++)        if (i==1||a[i].x!=a[i-1].x) a[++m]=a[i];    for (int i=1;i<=m;i++) b[i]=a[i].y;    sort(b+1,b+m+1);    for (int i=1;i<=m;i++)        for (int j=1;j<=m;j++)            if (a[i].y==b[j]){                c[i]=j; break;            }     for (int i=m;i;i--)        for (int j=i;j<=m;j++)            for (int k=m;k;k--){                f[i][j][k]=105;                for (int t=i;t<j;t++)                    f[i][j][k]=min(f[i][j][k],f[i][t][k]+f[t+1][j][k]);                int l,r,x,y;                for (l=i;l<=j;l++)                    if (c[l]>=k) break;                for (r=j;r>=i;r--)                    if (c[r]>=k) break;                if (l>r){                    f[i][j][k]=0;                    continue;                }                if (l==r){                    f[i][j][k]=1;                    continue;                }                x=a[r].x-a[l].x; y=A/x;                for (l=i;l<=j;l++)                    if (a[l].y>y) break;                for (r=j;r>=i;r--)                    if (a[r].y>y) break;                x=105;                for (int t=l;t<=r;t++)                    if (a[t].y>y&&c[t]<x) x=c[t];                f[i][j][k]=min(f[i][j][k],f[l][r][x]+1);            }    printf("%d",f[1][m][1]);}
原创粉丝点击